{"record":{"id":"d131e8d0ba764ba3","repo":"remotion-dev/remotion","slug":"expected-stco-box-in-trak-box","errorCode":null,"errorMessage":"Expected stco box in trak box","messagePattern":"Expected stco box in trak box","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/collect-sample-positions-from-trak.ts","lineNumber":38,"sourceCode":"\t\treturn getGroupedSamplesPositionsFromMp4({\n\t\t\ttrakBox,\n\t\t\tbigEndian: shouldGroupSamples.bigEndian,\n\t\t});\n\t}\n\n\tconst stszBox = getStszBox(trakBox);\n\tconst stcoBox = getStcoBox(trakBox);\n\tconst stscBox = getStscBox(trakBox);\n\tconst stssBox = getStssBox(trakBox);\n\tconst sttsBox = getSttsBox(trakBox);\n\tconst cttsBox = getCttsBox(trakBox);\n\n\tif (!stszBox) {\n\t\tthrow new Error('Expected stsz box in trak box');\n\t}\n\n\tif (!stcoBox) {\n\t\tthrow new Error('Expected stco box in trak box');\n\t}\n\n\tif (!stscBox) {\n\t\tthrow new Error('Expected stsc box in trak box');\n\t}\n\n\tif (!sttsBox) {\n\t\tthrow new Error('Expected stts box in trak box');\n\t}\n\n\tif (!timescaleAndDuration) {\n\t\tthrow new Error('Expected timescale and duration in trak box');\n\t}\n\n\tconst samplePositions = getSamplePositions({\n\t\tstcoBox,\n\t\tstscBox,\n\t\tstszBox,","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/collect-sample-positions-from-trak.ts#L20-L56","documentation":"Thrown by collectSamplePositionsFromTrak when a trak box lacks an stco (Sample-to-Chunk Offset / 64-bit co64 variant) box. The stco box maps each chunk to its absolute file byte offset, which is mandatory for computing where samples live in a non-fragmented (progressive) MP4. Without it the parser cannot build sample positions for seeking or track construction. ISOBMFF/MP4 spec (ISO/IEC 14496-12) requires stco or co64 in every well-formed stbl/minf/stbl hierarchy.","triggerScenarios":"Called when the media-parser walks a progressive (non-fragmented) MP4 trak whose stbl is missing the stco child. This happens if the file was written by a tool that omits stco, if the trak is a hint/track that uses a different offset scheme, or if the box was stripped/truncated by a transcode remux that wrote co64 instead and the parser's traversal does not fold co64 into getStcoBox for this code path.","commonSituations":"Corrupt or half-written MP4 files (interrupted download, truncated upload). Files produced by non-standard muxers (some HLS packagers, older ffmpeg profiles, screen recorders). Files where the offset table is stored as co64 (64-bit) rather than stco (32-bit) and the parser version does not unify them.","solutions":["Re-mux the source with a recent ffmpeg build using `ffmpeg -i input.mp4 -c copy -movflags faststart remuxed.mp4` to regenerate a complete stbl with stco.","Verify the file integrity with `ffprobe -v error -show_streams input.mp4`; if ffprobe reports a malformed track, treat the file as unsupported.","If you control the muxing pipeline, ensure it emits a 32-bit stco (or confirm the parser build you target unifies co64).","Guard the parse call in a try/catch and surface a user-facing 'unsupported/corrupt file' message rather than crashing."],"exampleFix":"// before\nconst positions = collectSamplePositionsFromTrak(trakBox);\n\n// after\ntry {\n  const positions = collectSamplePositionsFromTrak(trakBox);\n} catch (err) {\n  throw new Error(`Cannot seek this MP4: ${err instanceof Error ? err.message : err}. Re-mux the file with ffmpeg -movflags faststart.`);\n}","handlingStrategy":"try-catch","validationCode":"// Probe the file's sample table completeness before parsing deeply\nimport {execFileSync} from 'node:child_process';\nfunction hasStco(file: string): boolean {\n  const out = execFileSync('ffprobe', ['-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=index', '-of', 'json', file], {encoding: 'utf8'});\n  return !/error|invalid/i.test(out);\n}","typeGuard":"import type {TrakBox} from './trak/trak';\nimport {getStcoBox} from './traversal';\nfunction trakHasStco(trakBox: TrakBox): boolean {\n  return getStcoBox(trakBox) !== null;\n}","tryCatchPattern":"try {\n  const positions = collectSamplePositionsFromTrak(trakBox);\n} catch (err) {\n  if (/Expected stco box/i.test(String(err?.message))) {\n    return { seekable: false, reason: 'missing-stco' };\n  }\n  throw err;\n}","preventionTips":["Always faststart-re-mux user-uploaded MP4s before parsing them.","Run ffprobe as an upload-validation step and reject files reporting errors.","Keep the parsing path inside a try/catch at the API boundary and map known 'Expected X box' messages to user-facing 'unsupported file' errors.","Do not assume box presence — store moov/trak boxes you have already validated and reuse them."],"tags":["mp4","isobmff","media-parser","corrupt-file","seeking"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}