{"record":{"id":"457d975040357bd5","repo":"remotion-dev/remotion","slug":"unsupported-ctts-version-version","errorCode":null,"errorMessage":"Unsupported CTTS version ${version}","messagePattern":"Unsupported CTTS version (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/stsd/ctts.ts","lineNumber":28,"sourceCode":"\ttype: 'ctts-box';\n\tversion: number;\n\tflags: number[];\n\tentryCount: number;\n\tentries: CttsEntry[];\n}\n\nexport const parseCtts = ({\n\titerator,\n\toffset,\n\tsize,\n}: {\n\titerator: BufferIterator;\n\toffset: number;\n\tsize: number;\n}): CttsBox => {\n\tconst version = iterator.getUint8();\n\tif (version !== 0 && version !== 1) {\n\t\tthrow new Error(`Unsupported CTTS version ${version}`);\n\t}\n\n\tconst flags = iterator.getSlice(3);\n\tconst entryCount = iterator.getUint32();\n\n\tconst entries: CttsEntry[] = [];\n\n\tfor (let i = 0; i < entryCount; i++) {\n\t\tconst sampleCount = iterator.getUint32();\n\n\t\t// V1 = signed, V0 = unsigned\n\t\t// however some files are buggy\n\n\t\t// Let's do the same thing as mp4box\n\t\t// https://github.com/gpac/mp4box.js/blob/c6cc468145bc5b031b866446111f29c8b620dbe6/src/parsing/ctts.js#L2\n\t\tconst sampleOffset = iterator.getInt32();\n\n\t\tentries.push({","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/stsd/ctts.ts#L10-L46","documentation":"The CTTS (Composition Time to Sample) box declares a version byte other than 0 or 1. Version 0 stores unsigned offsets and version 1 stores signed offsets; both are the only standardized versions. Any other value means the box is malformed or the parser is misaligned (read the wrong byte as the version).","triggerScenarios":"Calling parseCtts on a CTTS box where the first byte (version) is not 0 or 1. This usually means the iterator is reading garbage because an earlier box was parsed with the wrong size, pushing the cursor into the middle of unrelated data.","commonSituations":"Corrupt or truncated MP4 files, files produced by non-conformant encoders, or files where a preceding box parser consumed too many/few bytes and desynchronized the cursor. Rarely a genuinely novel version.","solutions":["Validate the file with mp4box/ffprobe: `ffprobe -v error -show_format input.mp4` — if ffprobe also errors, the file is corrupt.","Check whether an earlier box in the same moov/traf threw a size-mismatch error; cursor desync is the most common root cause.","Re-mux the file with `ffmpeg -i input.mp4 -c copy -movflags +faststart remuxed.mp4` to normalize box layout.","If the source is a live stream or fragmented MP4, ensure the moof/traf chain is complete and not truncated mid-flight."],"exampleFix":"// before: corrupted moov produces CTTS version 0xff\nffmpeg -i corrupt.mp4 -c copy fixed.mp4\n// after: re-mux regates a well-formed CTTS v0/v1","handlingStrategy":"try-catch","validationCode":"// Validate the CTTS box version byte before parsing\nfunction isValidCttsVersion(versionByte: number): boolean {\n  return versionByte === 0 || versionByte === 1;\n}\n// Read the version byte at the box's data offset and check before invoking parseMedia","typeGuard":"function isSupportedCttsVersion(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 CTTS version')) {\n    // file likely corrupt or cursor-desynced; re-mux or reject\n  } else throw err;\n}","preventionTips":["Pre-validate uploads with ffprobe before parsing.","Treat any 'Unsupported X version' error as a symptom and inspect earlier boxes for the real cause.","Keep uncorrupted backups so re-muxing is always an option."],"tags":["media-parser","isobmff","ctts-box","corrupt-file","mp4"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}