{"record":{"id":"072d43703a8dc65c","repo":"remotion-dev/remotion","slug":"expected-wave-got-filetype","errorCode":null,"errorMessage":"Expected WAVE, got ${fileType}","messagePattern":"Expected WAVE, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/wav/parse-header.ts","lineNumber":13,"sourceCode":"import type {ParseResult} from '../../parse-result';\nimport type {ParserState} from '../../state/parser-state';\nimport type {WavHeader} from './types';\n\nexport const parseHeader = ({\n\tstate,\n}: {\n\tstate: ParserState;\n}): Promise<ParseResult> => {\n\tconst fileSize = state.iterator.getUint32Le();\n\tconst fileType = state.iterator.getByteString(4, false);\n\tif (fileType !== 'WAVE') {\n\t\tthrow new Error(`Expected WAVE, got ${fileType}`);\n\t}\n\n\tconst header: WavHeader = {\n\t\ttype: 'wav-header',\n\t\tfileSize,\n\t};\n\n\tstate.structure.getWavStructure().boxes.push(header);\n\n\treturn Promise.resolve(null);\n};\n","sourceCodeStart":1,"sourceCodeEnd":25,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/wav/parse-header.ts#L1-L25","documentation":"parseHeader reads the 4 bytes after the RIFF size — the RIFF form-type — and requires ASCII 'WAVE'. Any other form-type means the file is a RIFF container but not a WAV (e.g. 'AVI ', 'RDIB', 'RMID'), so the WAV parser refuses it. This is the first integrity gate after the container sniffer routed the stream to the WAV parser.","triggerScenarios":"A non-WAV RIFF file (AVI, RMI, RDIB) routed to the WAV parser, or a corrupted/truncated file whose form-type bytes are not 'WAVE'. Also triggers if a wrong file (non-RIFF) was force-routed to the WAV parser.","commonSituations":"Wrong file extension (AVI renamed .wav); truncated header; bytes flipped by a bad transfer; misidentified container.","solutions":["Verify the file type: `file <path>` and ffprobe.","Provide a real WAV, or use the correct parser for the actual container.","Sniff the first 12 bytes yourself (RIFF....WAVE) before calling parseMedia().","Use Mediabunny, which sniffs containers more robustly; try/catch."],"exampleFix":"// before\nawait parseMedia({ src: maybeWav });\n\n// after — sniff the RIFF/WAVE magic first\nconst buf = await readFirstNBytes(maybeWav, 12);\nconst isWav = buf[0] === 0x52 && buf.subarray(8, 12).toString() === 'WAVE';\nif (!isWav) throw new Error('not a WAV');\nawait parseMedia({ src: maybeWav });","handlingStrategy":"validation","validationCode":"// sniff the RIFF/WAVE magic before parsing\nimport { promises as fs } from 'fs';\nconst fd = await fs.open(path, 'r');\nconst buf = Buffer.alloc(12);\nawait fd.read(buf, 0, 12, 0);\nawait fd.close();\nconst isWav = buf.toString('ascii', 0, 4) === 'RIFF' && buf.toString('ascii', 8, 12) === 'WAVE';\nif (!isWav) throw new Error('not a WAV file');","typeGuard":"const isWavFile = (head: Uint8Array) =>\n  head.length >= 12 &&\n  head[0] === 0x52 && head[1] === 0x49 && head[2] === 0x46 && head[3] === 0x46 &&\n  head[8] === 0x57 && head[9] === 0x41 && head[10] === 0x56 && head[11] === 0x45;","tryCatchPattern":"try {\n  await parseMedia({ src });\n} catch (err) {\n  if (err instanceof Error && /Expected WAVE/.test(err.message)) {\n    // wrong container — route to the right parser or reject\n  } else throw err;\n}","preventionTips":["Sniff the 12-byte RIFF/WAVE header before calling parseMedia().","Don't trust file extensions; validate magic bytes.","Use Mediabunny for more robust container detection."],"tags":["wav","media-parser","corrupt-file","container","unsupported-format"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}