remotion-dev/remotion · error · TypeError

outputs.${layer} cannot specify both outputTarget and output

Error message

outputs.${layer} cannot specify both outputTarget and outputWritable.

What it means

A layer output may specify either outputTarget (built-in sink selection) or outputWritable (a custom WritableStream sink), but not both — they are conflicting ways to choose where bytes go. Specifying both raises this TypeError to avoid ambiguous output behavior.

Source

Thrown at packages/video-matting/src/separate-video-layers.ts:132

	if (!output || typeof output !== 'object' || Array.isArray(output)) {
		throw new TypeError(`outputs.${layer} must be an object.`);
	}

	if (
		output.outputTarget !== undefined &&
		output.outputTarget !== 'arraybuffer' &&
		output.outputTarget !== 'web-fs'
	) {
		throw new TypeError(
			`outputs.${layer}.outputTarget must be arraybuffer or web-fs.`,
		);
	}

	if (
		output.outputTarget !== undefined &&
		output.outputWritable !== undefined
	) {
		throw new TypeError(
			`outputs.${layer} cannot specify both outputTarget and outputWritable.`,
		);
	}

	if (output.outputWritable !== undefined) {
		if (
			typeof WritableStream === 'undefined' ||
			!(output.outputWritable instanceof WritableStream)
		) {
			throw new TypeError(
				`outputs.${layer}.outputWritable must be a WritableStream.`,
			);
		}

		if (output.outputWritable.locked) {
			throw new TypeError(
				`outputs.${layer}.outputWritable must not already be locked.`,
			);

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Remove outputTarget when you supply outputWritable (the writable takes over as the sink).
  2. Remove outputWritable when you want the built-in 'arraybuffer' or 'web-fs' target.
  3. When merging configs, delete conflicting keys instead of naively spreading.

Example fix

// before
outputs: {video: {outputTarget: 'arraybuffer', outputWritable: stream}}
// after
outputs: {video: {outputWritable: stream}}
Defensive patterns

Strategy: validation

Validate before calling

if (out.outputTarget !== undefined && out.outputWritable !== undefined) throw new TypeError('choose either outputTarget or outputWritable');

Type guard

null

Try / catch

try { await separateVideoLayers(opts); } catch (e) { if (e instanceof TypeError && e.message.includes('both outputTarget and outputWritable')) { delete layerConfig.outputTarget; await separateVideoLayers(opts); } else throw e; }

Prevention

When it happens

Trigger: Calling separateVideoLayers({outputs: {video: {outputTarget: 'arraybuffer', outputWritable: myStream}}}).

Common situations: Merging default config (outputTarget) with user config (outputWritable) via object spread; adding outputWritable without removing the default outputTarget.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/60d20a6032a32b73. Report an issue: GitHub.