remotion-dev/remotion · error · TypeError
audio must be one of base, foreground, both, or none.
Error message
audio must be one of base, foreground, both, or none.
What it means
The audio option controls where the source audio is routed and must be one of the enumerated strings: 'base', 'foreground', 'both', or 'none'. Any other value is rejected with this TypeError (AUDIO_DESTINATIONS membership check).
Source
Thrown at packages/video-matting/src/separate-video-layers.ts:203
output: options.outputs?.foreground,
});
if (
options.outputs?.base?.outputWritable !== undefined &&
options.outputs.base.outputWritable ===
options.outputs.foreground?.outputWritable
) {
throw new TypeError(
'outputs.base and outputs.foreground must not use the same outputWritable.',
);
}
getVideoMattingModelInfo(options.model ?? 'modnet');
if (
options.audio !== undefined &&
!AUDIO_DESTINATIONS.includes(options.audio)
) {
throw new TypeError(
'audio must be one of base, foreground, both, or none.',
);
}
resolveVideoMattingQuality(options.videoBitrate ?? 'very-high');
resolveVideoMattingQuality(options.audioBitrate ?? 'medium');
if (
options.keyframeIntervalInSeconds !== undefined &&
(!Number.isFinite(options.keyframeIntervalInSeconds) ||
options.keyframeIntervalInSeconds <= 0)
) {
throw new TypeError(
'keyframeIntervalInSeconds must be a positive finite number.',
);
}
if (View on GitHub (pinned to b2f4e34732)
Solutions
- Set audio to exactly 'base', 'foreground', 'both', or 'none'
- Normalize/validate dynamic values against the allowed list before calling
- Omit audio to use the default
Example fix
// before
await separateVideoLayers({ src, outputs, audio: 'all' });
// after
await separateVideoLayers({ src, outputs, audio: 'both' }); Defensive patterns
Strategy: validation
Validate before calling
const AUDIO = ['base','foreground','both','none']; if (audio !== undefined && !AUDIO.includes(audio)) throw new TypeError(`audio must be one of ${AUDIO.join(', ')}`); Type guard
const isAudioDestination = (v) => ['base','foreground','both','none'].includes(v);
Try / catch
try { await separateVideoLayers({ src, outputs, audio }); } catch (e) { if (e instanceof TypeError && e.message.includes('audio must be one of')) { /* fix enum value */ } else throw e; } Prevention
- Copy enum values exactly from docs/types
- Trim and lowercase user/CLI-provided values before comparing
- Type the option as a union in TypeScript
When it happens
Trigger: Passing audio: 'audio' or 'all' or 'keep'; passing true/false; typo like 'foreground ' with whitespace or wrong case 'Foreground'.
Common situations: Guessing the enum from docs memory; loading the value from a CLI flag or env var without normalizing; copying an option name from a different Remotion API.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- "${name}" must be one of ${variants.join(', ')}
- No src passed
- The "freeze" prop is not supported on <Html5Audio />. Use <S
- The `<Html5Audio>` tag requires a string for `src`, but got
- Changing the AudioContext sample rate dynamically is not sup
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/0c7365767a6b212b.
Report an issue: GitHub.