{"record":{"id":"ff363a9eb885566a","repo":"remotion-dev/remotion","slug":"outputs-layer-must-be-an-object","errorCode":null,"errorMessage":"outputs.${layer} must be an object.","messagePattern":"outputs\\.(.+?) must be an object\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/video-matting/src/separate-video-layers.ts","lineNumber":115,"sourceCode":"const throwIfAborted = (signal: AbortSignal | undefined) => {\n\tif (signal?.aborted) {\n\t\tthrow createAbortError(signal);\n\t}\n};\n\nconst validateLayerOutputOptions = ({\n\tlayer,\n\toutput,\n}: {\n\tlayer: 'base' | 'foreground';\n\toutput: VideoLayerOutputOptions | undefined;\n}) => {\n\tif (output === undefined) {\n\t\treturn;\n\t}\n\n\tif (!output || typeof output !== 'object' || Array.isArray(output)) {\n\t\tthrow new TypeError(`outputs.${layer} must be an object.`);\n\t}\n\n\tif (\n\t\toutput.outputTarget !== undefined &&\n\t\toutput.outputTarget !== 'arraybuffer' &&\n\t\toutput.outputTarget !== 'web-fs'\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`outputs.${layer}.outputTarget must be arraybuffer or web-fs.`,\n\t\t);\n\t}\n\n\tif (\n\t\toutput.outputTarget !== undefined &&\n\t\toutput.outputWritable !== undefined\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`outputs.${layer} cannot specify both outputTarget and outputWritable.`,","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/video-matting/src/separate-video-layers.ts#L97-L133","documentation":"In separateVideoLayers(), each entry of the outputs option is validated by validateLayerOutputOptions. A per-layer output must be an object (or undefined); passing a primitive, string, null, or an array raises this TypeError naming the offending layer key.","triggerScenarios":"Calling separateVideoLayers({outputs: {video: true}}), outputs: {audio: 'file.mp4'}, outputs: {fg: []}, or outputs: {bg: null}.","commonSituations":"Config built from JSON where a layer is set to a string path or boolean flag; mistaking outputs for a flat record of file names; spreading arrays into outputs.","solutions":["Provide an options object per layer, e.g. {outputs: {video: {outputTarget: 'arraybuffer'}}}.","Move file paths/booleans into object fields like outputTarget or outputWritable.","Omit the layer key entirely instead of passing null when no output is wanted."],"exampleFix":"// before\nawait separateVideoLayers({input, outputs: {video: 'out.mp4'}});\n// after\nawait separateVideoLayers({input, outputs: {video: {outputTarget: 'arraybuffer'}}});","handlingStrategy":"type-guard","validationCode":"const isLayerOutput = (o: unknown): boolean => o === undefined || (!!o && typeof o === 'object' && !Array.isArray(o));\nObject.entries(outputs).forEach(([k, v]) => { if (!isLayerOutput(v)) throw new TypeError('outputs.' + k + ' must be an object'); });","typeGuard":"const isLayerOutput = (o: unknown): o is LayerOutputOptions | undefined => o === undefined || (!!o && typeof o === 'object' && !Array.isArray(o));","tryCatchPattern":"try { await separateVideoLayers(opts); } catch (e) { if (e instanceof TypeError && e.message.startsWith('outputs.')) { console.error('bad outputs config:', e.message); } throw e; }","preventionTips":["Validate the outputs object shape at config load time","Never store file paths or booleans directly as layer values","Use TypeScript types for the outputs option"],"tags":["typeerror","validation","options"],"backgroundTag":"schema-validation-failed","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-09-09T13:27:51.281Z","contentChangedAt":"2026-09-09T13:27:51.281Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}