{"record":{"id":"1c5bb1ed566b6f2e","repo":"nilaoda/N_m3u8DL-RE","slug":"a-trun-box-should-have-a-valid-version-value","errorCode":null,"errorMessage":"A TRUN box should have a valid version value","messagePattern":"A TRUN box should have a valid version value","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs","lineNumber":77,"sourceCode":"                .Box(\"traf\", MP4Parser.Children)\n                .FullBox(\"tfdt\", box =>\n                {\n                    sawTFDT = true;\n                    if (box.Version is not (0 or 1))\n                        throw new Exception(\"TFDT version can only be 0 or 1\");\n                    baseTime = MP4Parser.ParseTFDT(box.Reader, box.Version);\n                })\n                .FullBox(\"tfhd\", box =>\n                {\n                    if (box.Flags == 1000)\n                        throw new Exception(\"A TFHD box should have a valid flags value\");\n                    defaultDuration = MP4Parser.ParseTFHD(box.Reader, box.Flags).DefaultSampleDuration;\n                })\n                .FullBox(\"trun\", box =>\n                {\n                    sawTRUN = true;\n                    if (box.Version == 1000)\n                        throw new Exception(\"A TRUN box should have a valid version value\");\n                    if (box.Flags == 1000)\n                        throw new Exception(\"A TRUN box should have a valid flags value\");\n                    presentations = MP4Parser.ParseTRUN(box.Reader, box.Version, box.Flags).SampleData;\n                })\n                .Box(\"mdat\", MP4Parser.AllData(data =>\n                {\n                    if (sawMDAT)\n                        throw new Exception(\"VTT cues in mp4 with multiple MDAT are not currently supported\");\n                    sawMDAT = true;\n                    rawPayload = data;\n                }))\n                .Parse(dataSeg,/* partialOkay= */ false);\n\n            if (!sawMDAT && !sawTFDT && !sawTRUN)\n            {\n                throw new Exception(\"A required box is missing\");\n            }\n","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/nilaoda/N_m3u8DL-RE/blob/e113dee70c924ee08dae5460624909b04d84cb76/src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before calling ExtractSub, verify the fragment contains a readable trun box\nif (!dataSeg.Take(16).ToArray().Any(b => true)) throw new ArgumentException(\"empty segment\");\n// stronger: scan boxes and confirm trun version is 0 or 1 using an MP4 box walker","typeGuard":"bool HasValidTrun(byte[] seg) => Mp4BoxScanner.Find(seg, \"trun\") is { } b && b.Version is 0 or 1;","tryCatchPattern":"try { var subs = MP4VttUtil.ExtractSub(dataSeg, baseTime); }\ncatch (Exception ex) when (ex.Message.Contains(\"valid version value\")) {\n    logger.Warn(\"Corrupt trun box, re-downloading segment\");\n    dataSeg = await reDownloadAsync(segmentUrl);\n}","preventionTips":["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."],"tags":["mp4","corrupt-segment","subtitles"],"backgroundTag":"unexpected-response-shape","analyzedSha":"e113dee70c924ee08dae5460624909b04d84cb76","analyzedAt":"2026-09-13T02:43:21.078Z","contentChangedAt":"2026-09-13T02:43:21.078Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}