nilaoda/N_m3u8DL-RE · error · Exception
A TRUN box should have a valid version value
Error message
A TRUN box should have a valid version value
What it means
MP4VttUtil.ExtractSub parses a WVTTEncrypted/fragmented MP4 segment to extract WebVTT cues. When it encounters the 'trun' (Track Fragment Run) full box, it requires a recognized box version; a version of 1000 is the sentinel value MP4Parser uses when the box's version byte could not be read (e.g. the box is truncated or malformed). The library throws to avoid calling ParseTRUN with an invalid version that would corrupt sample parsing.
Solutions
- Re-download the affected media segment; verify it is a complete, valid MP4 fragment (starts with a valid 'trun' box version 0 or 1).
- Check the stream server/CDN is serving correct bytes (compare segment size/hash against the playlist).
- Skip or re-fetch the failing segment in the download pipeline instead of treating it as fatal.
- Inspect the segment with an MP4 box inspector (e.g. Bento4 mp4dump) to confirm the trun box structure.
Defensive patterns
Strategy: validation
Validate before calling
// before calling ExtractSub, verify the fragment contains a readable trun box
if (!dataSeg.Take(16).ToArray().Any(b => true)) throw new ArgumentException("empty segment");
// stronger: scan boxes and confirm trun version is 0 or 1 using an MP4 box walker Type guard
bool HasValidTrun(byte[] seg) => Mp4BoxScanner.Find(seg, "trun") is { } b && b.Version is 0 or 1; Try / catch
try { var subs = MP4VttUtil.ExtractSub(dataSeg, baseTime); }
catch (Exception ex) when (ex.Message.Contains("valid version value")) {
logger.Warn("Corrupt trun box, re-downloading segment");
dataSeg = await reDownloadAsync(segmentUrl);
} Prevention
- Verify segment integrity (size/hash) after download before parsing.
- Handle non-200 responses before passing bytes to the parser.
- Re-download truncated segments automatically.
- Validate fragments with an MP4 box inspector in tests.
When it happens
Trigger: ExtractSub is called on a segment whose 'trun' box is truncated so its version byte cannot be read, or the MP4 data is corrupt/misinterpreted so the version field parses as the sentinel 1000.
Common situations: Downloading a truncated or corrupted media segment from a flaky CDN; a server returning an HTML error page or partial bytes in place of an m4s segment; mis-typed muxed streams in an HLS/WVTT stream.
Related errors
- A TRUN box should have a valid flags value
- The samples do not fit evenly into the sample sizes given…
- VTT cues in mp4 with multiple MDAT are not currently…
- A required box is missing
- WVTT sample duration unknown, and no default found!
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/1c5bb1ed566b6f2e.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs:77
.Box("traf", MP4Parser.Children)
.FullBox("tfdt", box =>
{
sawTFDT = true;
if (box.Version is not (0 or 1))
throw new Exception("TFDT version can only be 0 or 1");
baseTime = MP4Parser.ParseTFDT(box.Reader, box.Version);
})
.FullBox("tfhd", box =>
{
if (box.Flags == 1000)
throw new Exception("A TFHD box should have a valid flags value");
defaultDuration = MP4Parser.ParseTFHD(box.Reader, box.Flags).DefaultSampleDuration;
})
.FullBox("trun", box =>
{
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");
}
View on GitHub (pinned to e113dee70c)