{"record":{"id":"073884a4b0493747","repo":"remotion-dev/remotion","slug":"outputs-layer-outputwritable-must-be-a-writable","errorCode":null,"errorMessage":"outputs.${layer}.outputWritable must be a WritableStream.","messagePattern":"outputs\\.(.+?)\\.outputWritable must be a WritableStream\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/video-matting/src/separate-video-layers.ts","lineNumber":142,"sourceCode":"\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.`,\n\t\t);\n\t}\n\n\tif (output.outputWritable !== undefined) {\n\t\tif (\n\t\t\ttypeof WritableStream === 'undefined' ||\n\t\t\t!(output.outputWritable instanceof WritableStream)\n\t\t) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`outputs.${layer}.outputWritable must be a WritableStream.`,\n\t\t\t);\n\t\t}\n\n\t\tif (output.outputWritable.locked) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`outputs.${layer}.outputWritable must not already be locked.`,\n\t\t\t);\n\t\t}\n\t}\n};\n\nconst validateOptions = (options: SeparateVideoLayersOptions) => {\n\tif (!options || typeof options !== 'object') {\n\t\tthrow new TypeError('separateVideoLayers() expects an options object.');\n\t}\n\n\tconst isBlob = typeof Blob !== 'undefined' && options.src instanceof Blob;","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/video-matting/src/separate-video-layers.ts#L124-L160","documentation":"separateVideoLayers() validates each layer's output options. When you pass outputs.<layer>.outputWritable, it must be an actual Web WritableStream instance; anything else (a Node.js stream, a string path, a plain object) is rejected with this TypeError because the library pipes MediaRecorder/WebCodecs output into it via the standard streams API.","triggerScenarios":"Passing outputs.base.outputWritable or outputs.foreground.outputWritable set to a Node stream (fs.createWriteStream), a file path string, null (non-undefined), a WritableStream-like duck-typed object, or running in an environment without WritableStream defined (old Node/runtime without web streams).","commonSituations":"Confusing Node.js fs write streams with Web WritableStreams in SSR/Node scripts; passing a file path instead of a stream; forgetting to import WritableStream from a polyfill in older runtimes; reusing a writable that was already handed to another consumer.","solutions":["Pass a Web WritableStream, e.g. new WritableStream({...}) or one obtained from a TransformStream","If you have a Node stream, wrap/convert it to a Web WritableStream (e.g. node:stream/web Writable.toWeb(nodeStream))","Remove the outputWritable property entirely so the library uses its default output handling","Ensure the runtime supports web streams (Node >= 18, modern browsers)"],"exampleFix":"// before\nawait separateVideoLayers({ src: 'video.mp4', outputs: { base: { outputWritable: fs.createWriteStream('base.mp4') } } });\n// after\nimport { Writable } from 'node:stream/web';\nawait separateVideoLayers({ src: 'video.mp4', outputs: { base: { outputWritable: Writable.toWeb(fs.createWriteStream('base.mp4')) } } });","handlingStrategy":"type-guard","validationCode":"function assertWritable(s) { if (s !== undefined && !(typeof WritableStream !== 'undefined' && s instanceof WritableStream)) throw new TypeError('outputWritable must be a Web WritableStream'); }","typeGuard":"const isWritableStream = (v) => typeof WritableStream !== 'undefined' && v instanceof WritableStream;","tryCatchPattern":"try { await separateVideoLayers(opts); } catch (e) { if (e instanceof TypeError && e.message.includes('outputWritable must be a WritableStream')) { /* fix stream construction */ } else throw e; }","preventionTips":["Only pass Web WritableStream instances (browser or node:stream/web)","Convert Node streams with Writable.toWeb()","Never pass file paths where a stream is expected"],"tags":["type-mismatch","validation","writable-stream"],"backgroundTag":"type-mismatch","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"}