nilaoda/N_m3u8DL-RE · error · Exception
A required box is missing
Error message
A required box is missing
What it means
After parsing the segment, ExtractSub verifies it saw at least one of the required boxes: 'mdat' (cue payload), 'tfdt' (base media decode time), or 'trun' (sample runs). If none were present, the data is not a valid fragmented MP4 WVTT segment, so it throws "A required box is missing".
Solutions
- Verify the segment URL returns actual MP4 fragment bytes (check magic 'styp'/'moof' boxes), not HTML or an empty body.
- Check the HTTP response status/content-type for the segment request and handle non-200 before parsing.
- Re-download or retry the segment; ensure the playlist (m3u8) is current.
- Confirm the stream is genuinely an fMP4 WebVTT (wvtt) segment via INIT mp4 and codec info.
Defensive patterns
Strategy: validation
Validate before calling
// reject non-MP4 payloads before parsing
static bool LooksLikeFmp4(byte[] b) => b.Length > 12 &&
(System.Text.Encoding.ASCII.GetString(b, 4, 4) is "styp" or "moof" or "ftyp");
if (!LooksLikeFmp4(dataSeg)) throw new InvalidDataException("segment is not an fMP4 fragment"); Try / catch
try { var subs = MP4VttUtil.ExtractSub(dataSeg, baseTime); }
catch (Exception ex) when (ex.Message == "A required box is missing") {
logger.Error($"Segment from {segmentUrl} is not a valid fMP4 fragment (first bytes: {head})");
throw new SegmentFetchException(segmentUrl, inner: ex);
} Prevention
- Check HTTP status and content-type before parsing segments.
- Verify the first box type bytes are styp/moof/ftyp.
- Keep playlists fresh; tokenized segment URLs expire.
- Handle servers returning HTML with 200 status.
When it happens
Trigger: ExtractSub is called with a dataSeg that is not an MP4 fragment at all (wrong content type, HTML error page, empty/truncated bytes) so no mdat/tfdt/trun boxes parse.
Common situations: Playlist points to a wrong or moved segment URL; server returns an error page with 200 status; content mistakenly treated as fMP4 when it is actually a different container; zero-byte segments from a failed mirror.
Related errors
- A TRUN box should have a valid version value
- A TRUN box should have a valid flags value
- VTT cues in mp4 with multiple MDAT are not currently…
- WVTT sample duration unknown, and no default found!
- The samples do not fit evenly into the sample sizes given…
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/5f3410075f445b98.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs:93
sawTRUN = true;
if (box.Version == 1000)
throw new Exception("A TRUN box should have a valid version value");
if (box.Flags == 1000)
throw new Exception("A TRUN box should have a valid flags value");
presentations = MP4Parser.ParseTRUN(box.Reader, box.Version, box.Flags).SampleData;
})
.Box("mdat", MP4Parser.AllData(data =>
{
if (sawMDAT)
throw new Exception("VTT cues in mp4 with multiple MDAT are not currently supported");
sawMDAT = true;
rawPayload = data;
}))
.Parse(dataSeg,/* partialOkay= */ false);
if (!sawMDAT && !sawTFDT && !sawTRUN)
{
throw new Exception("A required box is missing");
}
var currentTime = baseTime;
var reader = new BinaryReader2(new MemoryStream(rawPayload!));
foreach (var presentation in presentations)
{
var duration = presentation.SampleDuration == 0 ? defaultDuration : presentation.SampleDuration;
var startTime = presentation.SampleCompositionTimeOffset != 0 ?
baseTime + presentation.SampleCompositionTimeOffset :
currentTime;
currentTime = startTime + duration;
var totalSize = 0;
do
{
// Read the payload size.
var payloadSize = (int)reader.ReadUInt32();
totalSize += payloadSize;View on GitHub (pinned to e113dee70c)