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

  1. Verify the file type: `file <path>` and ffprobe.
  2. Provide a real WAV, or use the correct parser for the actual container.
  3. Sniff the first 12 bytes yourself (RIFF....WAVE) before calling parseMedia().
  4. 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

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


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/072d43703a8dc65c. Report an issue: GitHub.