{"record":{"id":"beb39bc8e90bd77d","repo":"remotion-dev/remotion","slug":"expected-stsz-box-in-trak-box-beb39b","errorCode":null,"errorMessage":"Expected stsz box in trak box","messagePattern":"Expected stsz box in trak box","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/get-sample-positions-from-mp4.ts","lineNumber":34,"sourceCode":"\tbigEndian,\n}: {\n\ttrakBox: TrakBox;\n\tbigEndian: boolean;\n}): SamplePosition[] => {\n\tconst stscBox = getStscBox(trakBox);\n\tconst stszBox = getStszBox(trakBox);\n\tconst stcoBox = getStcoBox(trakBox);\n\n\tif (!stscBox) {\n\t\tthrow new Error('Expected stsc 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 (!stszBox) {\n\t\tthrow new Error('Expected stsz box in trak box');\n\t}\n\n\tif (stszBox.countType !== 'fixed') {\n\t\tthrow new Error('Only supporting fixed count type in stsz box');\n\t}\n\n\tconst samples: SamplePosition[] = [];\n\n\tlet timestamp = 0;\n\n\tconst stscKeys = Array.from(stscBox.entries.keys());\n\tfor (let i = 0; i < stcoBox.entries.length; i++) {\n\t\tconst entry = stcoBox.entries[i];\n\t\tconst chunk = i + 1;\n\t\tconst stscEntry = stscKeys.findLast((e) => e <= chunk);\n\t\tif (stscEntry === undefined) {\n\t\t\tthrow new Error('should not be');\n\t\t}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/get-sample-positions-from-mp4.ts#L16-L52","documentation":"Thrown by getGroupedSamplesPositionsFromMp4 when the TrakBox has no stsz (sample-size) box. stsz declares the size of each sample (or a fixed size for all); without it the parser cannot compute chunk sizes or sample counts, so it throws. The grouped-samples path specifically requires a populated stsz.","triggerScenarios":"Trak whose stbl lacks stsz. Truncated MP4s, repaired files, or traks (hint/tmcd) that legitimately omit sample sizes. Files where stsz lives in a fragment rather than the moov.","commonSituations":"Processing partially written MP4 files. Handling non-media traks. Encountering fragmented MP4s during early parsing.","solutions":["Re-mux with ffmpeg to regenerate complete sample tables including stsz.","Skip traks that do not carry media samples (hint, tmcd, chapter) before computing positions.","Wrap in try/catch and treat the trak as unsampleable."],"exampleFix":"// before\nconst positions = getGroupedSamplesPositionsFromMp4({trakBox, bigEndian});\n\n// after\nlet positions = [];\ntry {\n  positions = getGroupedSamplesPositionsFromMp4({trakBox, bigEndian});\n} catch (err) {\n  console.warn('trak missing stsz, skipping', err);\n}","handlingStrategy":"type-guard","validationCode":"import {getStszBox} from '@remotion/media-parser/containers/iso-base-media/traversal';\nif (getStszBox(trakBox)) { getGroupedSamplesPositionsFromMp4({trakBox, bigEndian}); }","typeGuard":"const hasStsz = (trak: TrakBox): boolean => getStszBox(trak) !== null;","tryCatchPattern":"try { getGroupedSamplesPositionsFromMp4({trakBox, bigEndian}); } catch (e) { if (e.message === 'Expected stsz box in trak box') { /* skip trak */ } else throw e; }","preventionTips":["Verify stsz presence before computing positions.","Skip non-media traks that omit stsz.","Re-mux incomplete MP4 files."],"tags":["mp4","samples","stsz","corrupt-file"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}