remotion-dev/remotion · error · TypeError
outputs must be an object.
Error message
outputs must be an object.
What it means
validateOptions for separateVideoLayers() checks that options.outputs, when provided, is a non-null object (and not an array). It maps foreground/base output targets by layer key, so a malformed outputs value would break per-layer validation and is rejected up front.
Source
Thrown at packages/video-matting/src/separate-video-layers.ts:176
}
const isBlob = typeof Blob !== 'undefined' && options.src instanceof Blob;
const isUrl = options.src instanceof URL;
if (typeof options.src !== 'string' && !isUrl && !isBlob) {
throw new TypeError('src must be a string, URL, or Blob.');
}
if (typeof options.src === 'string' && options.src.length === 0) {
throw new TypeError('src must not be an empty string.');
}
if (
options.outputs !== undefined &&
(!options.outputs ||
typeof options.outputs !== 'object' ||
Array.isArray(options.outputs))
) {
throw new TypeError('outputs must be an object.');
}
validateLayerOutputOptions({
layer: 'base',
output: options.outputs?.base,
});
validateLayerOutputOptions({
layer: 'foreground',
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.',
);View on GitHub (pinned to b2f4e34732)
Solutions
- Reshape to an object: { base: {...}, foreground: {...} }
- Remove outputs to use defaults (if base-only output is acceptable)
- Validate your loaded config's shape before calling
Example fix
// before
await separateVideoLayers({ src, outputs: [{ layer: 'base', outputPath: 'b.mp4' }] });
// after
await separateVideoLayers({ src, outputs: { base: { outputPath: 'b.mp4' } } }); Defensive patterns
Strategy: validation
Validate before calling
if (outputs !== undefined && (outputs === null || typeof outputs !== 'object' || Array.isArray(outputs))) throw new TypeError('outputs must be a plain object'); Type guard
const isOutputsObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
Try / catch
try { await separateVideoLayers({ src, outputs }); } catch (e) { if (e instanceof TypeError && e.message.includes('outputs must be an object')) { /* reshape config */ } else throw e; } Prevention
- Author outputs as { base: {...}, foreground: {...} } maps
- Validate JSON/YAML config shapes before invoking
When it happens
Trigger: Passing outputs: ['base','foreground'] (an array of layer names); passing null; JSON config where outputs is a list instead of a map.
Common situations: Misreading the API as taking a list of layers; config file authored with the wrong shape; YAML/JSON schema drift.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Output paths must be strings.
- outputs.${layer}.outputWritable must be a WritableStream.
- src must be a string, URL, or Blob.
- onProgress must be a function.
- Emoji ${emoji} not found. Available emojis: ${emojis.map((e)
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/c4befa82da1d9e8c.
Report an issue: GitHub.