{"record":{"id":"98c636a183da7740","repo":"remotion-dev/remotion","slug":"unsupported-trun-version-version","errorCode":null,"errorMessage":"Unsupported TRUN version ${version}","messagePattern":"Unsupported TRUN version (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/trun.ts","lineNumber":30,"sourceCode":"type TRunSample = {\n\tsampleDuration: number | null;\n\tsampleSize: number | null;\n\tsampleFlags: number | null;\n\tsampleCompositionTimeOffset: number | null;\n};\n\nexport const parseTrun = ({\n\titerator,\n\toffset,\n\tsize,\n}: {\n\titerator: BufferIterator;\n\toffset: number;\n\tsize: number;\n}): TrunBox => {\n\tconst version = iterator.getUint8();\n\tif (version !== 0 && version !== 1) {\n\t\tthrow new Error(`Unsupported TRUN version ${version}`);\n\t}\n\n\tconst flags = iterator.getUint24();\n\tconst sampleCount = iterator.getUint32();\n\n\tconst dataOffset = flags & 0x01 ? iterator.getInt32() : null;\n\tconst firstSampleFlags = flags & 0x04 ? iterator.getUint32() : null;\n\n\tconst samples: TRunSample[] = [];\n\n\tfor (let i = 0; i < sampleCount; i++) {\n\t\tconst sampleDuration = flags & 0x100 ? iterator.getUint32() : null;\n\t\tconst sampleSize = flags & 0x200 ? iterator.getUint32() : null;\n\t\tconst sampleFlags = flags & 0x400 ? iterator.getUint32() : null;\n\t\tconst sampleCompositionTimeOffset =\n\t\t\tflags & 0x800\n\t\t\t\t? version === 0\n\t\t\t\t\t? iterator.getUint32()","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/trun.ts#L12-L48","documentation":"The TRUN (Track Run) box parser only supports versions 0 and 1; any other version byte throws. TRUN v0 and v1 are the spec-standard versions (v1 adds signed composition offsets), so a value of 2+ indicates corruption or cursor desync in the surrounding traf.","triggerScenarios":"parseTrun reads a version byte other than 0 or 1 at the start of a trun box. Common when the preceding tfhd or saiz/saio box mis-sized and shifted the cursor.","commonSituations":"Corrupt fragmented MP4 (DASH/HLS) segments, partial segments, or files from buggy live packagers.","solutions":["Validate with `mp4box -info input.mp4` or `ffprobe -v error input.mp4`.","Re-fetch or re-mux: `ffmpeg -i segment.m4s -c copy -f mp4 remuxed.mp4`.","Inspect earlier thrown errors in the same parse session — a traf-level desync is the likely cause.","Ensure fMP4 segments are fully downloaded before parsing."],"exampleFix":"// before: traf desync makes trun read version 0x02\nffmpeg -i segment.m4s -c copy remuxed.mp4\n// after: trun reads version 0 or 1","handlingStrategy":"try-catch","validationCode":"function isValidTrunVersion(v: number): boolean {\n  return v === 0 || v === 1;\n}","typeGuard":"function isSupportedTrunVersion(v: number): v is 0 | 1 {\n  return v === 0 || v === 1;\n}","tryCatchPattern":"try {\n  await parseMedia({src, fields: {dimensions: true}});\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unsupported TRUN version')) {\n    // corrupt trun or upstream traf desync; re-mux or re-fetch segment\n  } else throw err;\n}","preventionTips":["Re-fetch incomplete DASH/HLS segments before parsing.","Investigate earlier traf-level parse errors first.","Use mp4box -info to validate fMP4 structure."],"tags":["media-parser","isobmff","trun-box","fragmented-mp4","corrupt-file","mp4"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}