{"record":{"id":"8f3e28a558453576","repo":"remotion-dev/remotion","slug":"unexpected-data-left-in-trun-box-left","errorCode":null,"errorMessage":"Unexpected data left in TRUN box: ${left}","messagePattern":"Unexpected data left in TRUN box: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/trun.ts","lineNumber":63,"sourceCode":"\t\tconst sampleCompositionTimeOffset =\n\t\t\tflags & 0x800\n\t\t\t\t? version === 0\n\t\t\t\t\t? iterator.getUint32()\n\t\t\t\t\t: iterator.getInt32()\n\t\t\t\t: null;\n\n\t\tsamples.push({\n\t\t\tsampleDuration,\n\t\t\tsampleSize,\n\t\t\tsampleFlags,\n\t\t\tsampleCompositionTimeOffset,\n\t\t});\n\t}\n\n\tconst currentOffset = iterator.counter.getOffset();\n\tconst left = size - (currentOffset - offset);\n\tif (left !== 0) {\n\t\tthrow new Error(`Unexpected data left in TRUN box: ${left}`);\n\t}\n\n\treturn {\n\t\ttype: 'trun-box',\n\t\tversion,\n\t\tsampleCount,\n\t\tdataOffset,\n\t\tfirstSampleFlags,\n\t\tsamples,\n\t};\n};\n","sourceCodeStart":45,"sourceCodeEnd":75,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/trun.ts#L45-L75","documentation":"After parsing all TRUN samples (conditionally reading duration, size, flags, composition offset per sample based on the flags bits), the parser checks that exactly zero bytes remain in the box. A non-zero 'left' value means a flag bit indicated a field that wasn't read, sampleCount didn't match actual data, or the box contains trailing/proprietary bytes.","triggerScenarios":"size - (currentOffset - offset) != 0 after the sample loop. Common when a trun flag bit is set that the parser doesn't handle, leaving fields unconsumed per sample, or when the declared size overstates the content.","commonSituations":"Fragmented MP4 with non-standard trun flag combinations, corrupt segments, or files from experimental encoders that pad trun boxes.","solutions":["Dump the trun box: `mp4dump input.mp4 | grep -A20 trun` to see flags, sampleCount, and size.","Re-mux: `ffmpeg -i input.mp4 -c copy -f mp4 -movflags +faststart remuxed.mp4`.","For HLS/DASH, re-fetch the offending segment.","Report upstream if standard trun flags are genuinely unhandled."],"exampleFix":"// before: trun with unhandled flag leaves leftover bytes\nffmpeg -i segment.m4s -c copy remuxed.mp4\n// after: trun left === 0","handlingStrategy":"try-catch","validationCode":"// Verify trun flag bits are all handled: 0x01 dataOffset, 0x04 firstSampleFlags,\n// per-sample: 0x100 duration, 0x200 size, 0x400 flags, 0x800 compositionOffset\nconst HANDLED_TRUN_FLAGS = 0x01 | 0x04 | 0x100 | 0x200 | 0x400 | 0x800;\nfunction hasUnhandledTrunFlags(flags: number): boolean {\n  return (flags & ~HANDLED_TRUN_FLAGS) !== 0;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await parseMedia({src, fields: {dimensions: true}});\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unexpected data left in TRUN box')) {\n    // unhandled trun flag or trailing bytes; re-mux or re-fetch\n  } else throw err;\n}","preventionTips":["Re-mux fMP4 with ffmpeg to normalize trun boxes.","Re-fetch suspicious HLS/DASH segments.","Inspect trun flags with mp4dump for non-standard packagers."],"tags":["media-parser","isobmff","trun-box","fragmented-mp4","corrupt-file","integrity-check","mp4"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}