{"record":{"id":"f9e0ab190762a41a","repo":"remotion-dev/remotion","slug":"expected-data-box","errorCode":null,"errorMessage":"Expected data box","messagePattern":"Expected data box","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/wav/get-duration-from-wav.ts","lineNumber":16,"sourceCode":"import type {ParserState} from '../../state/parser-state';\nimport type {WavData, WavFmt} from './types';\n\nexport const getDurationFromWav = (state: ParserState) => {\n\tconst structure = state.structure.getWavStructure();\n\n\tconst fmt = structure.boxes.find((b) => b.type === 'wav-fmt') as\n\t\t| WavFmt\n\t\t| undefined;\n\tif (!fmt) {\n\t\tthrow new Error('Expected fmt box');\n\t}\n\n\tconst dataBox = structure.boxes.find((b) => b.type === 'wav-data') as WavData;\n\tif (!dataBox) {\n\t\tthrow new Error('Expected data box');\n\t}\n\n\tconst durationInSeconds =\n\t\tdataBox.dataSize / (fmt.sampleRate * fmt.blockAlign);\n\treturn durationInSeconds;\n};\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/wav/get-duration-from-wav.ts#L1-L23","documentation":"Thrown while computing a WAV file's duration: getDurationFromWav walks the already-parsed box list and finds a 'wav-fmt' box but no 'wav-data' box. The duration formula (dataSize / (sampleRate * blockAlign)) needs the data chunk's size, so without it the parser aborts rather than guess. It surfaces when a caller requests a duration-derived field from parseMedia() on a WAV that never yielded a 'data' chunk.","triggerScenarios":"parseMedia({ src, fields: { durationInSeconds: true } }) (or any field that pulls duration) on a .wav whose 'data' chunk was never parsed: a file truncated after 'fmt ', a RIFF file whose samples live in a non-'data' chunk, or a stream parsed before the data chunk arrived.","commonSituations":"Partially-downloaded WAV; an encoder that wrote 'fmt ' then crashed before 'data'; reading a live/progressive stream too early; a file that is RIFF but not a real WAV (e.g. AVI renamed .wav).","solutions":["Verify the file reports a data chunk and a duration: ffprobe <file>.","Re-download or re-export the WAV so the 'data' chunk is complete.","Switch to Mediabunny (@mediabunny), the documented successor to @remotion/media-parser, which has broader WAV support.","Wrap parseMedia() in try/catch and skip or fall back for files that fail."],"exampleFix":"// before\nconst info = await parseMedia({ src: './clip.wav', fields: { durationInSeconds: true } });\n\n// after\ntry {\n  const info = await parseMedia({ src: './clip.wav', fields: { durationInSeconds: true } });\n} catch (err) {\n  // fall back to ffprobe for malformed/truncated WAVs\n  const dur = await getDurationViaFfprobe('./clip.wav');\n}","handlingStrategy":"try-catch","validationCode":"import { parseFile } from 'music-metadata'; // or ffprobe\n// Validate the WAV has a data chunk before parsing:\n// run `ffprobe -v error -show_entries format=duration -of default=nw=1 file.wav`\n// a non-empty duration means a data chunk was found.","typeGuard":null,"tryCatchPattern":"try {\n  const info = await parseMedia({ src, fields: { durationInSeconds: true } });\n} catch (err) {\n  if (err instanceof Error && /Expected data box/.test(err.message)) {\n    // WAV missing its data chunk — fall back to ffprobe or skip\n  } else throw err;\n}","preventionTips":["Validate WAVs with ffprobe before passing them to parseMedia().","Prefer Mediabunny (@mediabunny) over the deprecated @remotion/media-parser parseMedia().","Don't request duration-derived fields on streams you know are incomplete."],"tags":["wav","media-parser","corrupt-file","audio","duration"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}