remotion-dev/remotion · error · Error
Expected WAVE, got ${fileType}
Error message
Expected WAVE, got ${fileType} What it means
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.
Source
Thrown at packages/media-parser/src/containers/wav/parse-header.ts:13
import type {ParseResult} from '../../parse-result';
import type {ParserState} from '../../state/parser-state';
import type {WavHeader} from './types';
export const parseHeader = ({
state,
}: {
state: ParserState;
}): Promise<ParseResult> => {
const fileSize = state.iterator.getUint32Le();
const fileType = state.iterator.getByteString(4, false);
if (fileType !== 'WAVE') {
throw new Error(`Expected WAVE, got ${fileType}`);
}
const header: WavHeader = {
type: 'wav-header',
fileSize,
};
state.structure.getWavStructure().boxes.push(header);
return Promise.resolve(null);
};
View on GitHub (pinned to 78fe4bb3fd)
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.
Example fix
// before
await parseMedia({ src: maybeWav });
// after — sniff the RIFF/WAVE magic first
const buf = await readFirstNBytes(maybeWav, 12);
const isWav = buf[0] === 0x52 && buf.subarray(8, 12).toString() === 'WAVE';
if (!isWav) throw new Error('not a WAV');
await parseMedia({ src: maybeWav }); Defensive patterns
Strategy: validation
Validate before calling
// sniff the RIFF/WAVE magic before parsing
import { promises as fs } from 'fs';
const fd = await fs.open(path, 'r');
const buf = Buffer.alloc(12);
await fd.read(buf, 0, 12, 0);
await fd.close();
const isWav = buf.toString('ascii', 0, 4) === 'RIFF' && buf.toString('ascii', 8, 12) === 'WAVE';
if (!isWav) throw new Error('not a WAV file'); Type guard
const isWavFile = (head: Uint8Array) => head.length >= 12 && head[0] === 0x52 && head[1] === 0x49 && head[2] === 0x46 && head[3] === 0x46 && head[8] === 0x57 && head[9] === 0x41 && head[10] === 0x56 && head[11] === 0x45;
Try / catch
try {
await parseMedia({ src });
} catch (err) {
if (err instanceof Error && /Expected WAVE/.test(err.message)) {
// wrong container — route to the right parser or reject
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Wrong file extension (AVI renamed .wav); truncated header; bytes flipped by a bad transfer; misidentified container.
Related errors
- Unknown WAV box type ${type}
- File type ${fileType} not supported
- Expected data box
- Expected size 4 for fact box, got ${size}
- Only supporting WAVE with PCM audio format, but got ${audioF
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/072d43703a8dc65c.
Report an issue: GitHub.