Repository navigation
MatroskaExtractor crashes with NPE on nested ChapterAtom elements (regression in 1.11.0) #3438
Description
Version
Media3 1.11.1
More version details
Also reproduces on 1.11.0. Works on 1.10.1 (before Matroska chapter parsing was added to MatroskaExtractor).
Devices that reproduce the issue
- Robolectric (SDK 35) unit tests on JVM
- Not device-specific: the crash is in pure extractor parsing logic
Devices that do not reproduce the issue
None known on 1.11.x.
Reproducible in the demo app?
Not tested
Reproduction steps
- Take a Matroska file whose chapters are nested, i.e. a
ChapterAtomcontains childChapterAtoms. This is allowed by the spec:ChapterAtomis recursive (\Segment\Chapters\EditionEntry\+ChapterAtom, RFC 9559). - Extract it with
MatroskaExtractor, e.g. viaMetadataRetriever.retrieveTrackGroups()/retrieveDurationUs()or by playing it.
The file below was muxed with mkvmerge from this chapter XML using this script. mkvinfo (v102) parses it without warnings, and ffprobe reads its chapters without problems.
Structure:
EditionEntry
ChapterAtom "Introduction"
ChapterAtom "Getting Started"
ChapterAtom "Basic Concepts"
ChapterAtom "Main Content"
ChapterAtom "Advanced Techniques"
ChapterAtom "Practical Examples"
ChapterAtom "Conclusion"
Expected result
The file is extracted successfully: tracks and duration are reported and chapters are exposed (at least the top-level ones, ideally the nested ones too).
Actual result
MatroskaExtractor throws an NPE before any track is output:
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:902)
at androidx.media3.extractor.mkv.MatroskaExtractor.endMasterElement(MatroskaExtractor.java:978)
at androidx.media3.extractor.mkv.MatroskaExtractor$InnerEbmlProcessor.endMasterElement(MatroskaExtractor.java:2356)
at androidx.media3.extractor.mkv.DefaultEbmlReader.read(DefaultEbmlReader.java:88)
at androidx.media3.extractor.mkv.MatroskaExtractor.read(MatroskaExtractor.java:659)
Claude Analysis:
Cause: the extractor tracks a single currentChapter field instead of a stack. startMasterElement(ID_CHAPTER_ATOM) overwrites it with the nested atom, the nested atom's endMasterElement sets it to null, and the parent atom's endMasterElement then hits checkNotNull(currentChapter). A ChapterDisplay/ChapterTimeStart etc. following a nested atom inside the parent would similarly fail in getCurrentChapter().
Because the error is thrown while parsing, the whole file becomes unusable: MetadataRetriever fails for both track groups and duration, and the file can't be played, even though it is valid and worked in 1.10.1.
A side note on the symptom: under Robolectric, the MetadataRetriever future never completes (instead of failing), because MetadataRetrieverInternal only surfaces the prepare error through a sendEmptyMessageDelayed poll, and the paused looper's clock doesn't advance while the test thread is blocked waiting on the future.
Context: this blocks the Voice audiobook player from moving to 1.11 and adopting the new chapters API: PaulWoitaschek/Voice#3779
You can find the exact reproducer also here: PaulWoitaschek/Voice#3703
Media
https://github.com/PaulWoitaschek/Voice/raw/f827b30dc6d8db88d206332b70331dd31e38563c/core/scanner/src/test/resources/mka_nested_chapters.mka (~1 MB, silent AAC audio with nested chapters)
Activity
sandreas commentedon Oct 5, 2026
@icbaker
Reproduced the issue on my system. This is a nasty bug.
Support nested `ChapterAtom` elements in `MatroskaExtractor`
icbaker commentedon Oct 5, 2026
This is fixed by the commit linked above.