remotion-dev/remotion · error · TypeError

src must be a string, URL, or Blob.

Error message

src must be a string, URL, or Blob.

What it means

validateOptions for separateVideoLayers() requires options.src to identify the input video as a string path/URL, a URL object, or a Blob. Any other type (number, plain object, undefined) is rejected before the video is fetched or decoded.

Source

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

		}

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

const validateOptions = (options: SeparateVideoLayersOptions) => {
	if (!options || typeof options !== 'object') {
		throw new TypeError('separateVideoLayers() expects an options object.');
	}

	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,

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Pass a string path/URL, a new URL(...), or a Blob/File
  2. Convert bytes to a Blob: new Blob([buffer], { type: 'video/mp4' })
  3. Read the src from the correct variable/property (e.g. el.src instead of el)

Example fix

// before
await separateVideoLayers({ src: fileBuffer });
// after
await separateVideoLayers({ src: new Blob([fileBuffer], { type: 'video/mp4' }) });
Defensive patterns

Strategy: type-guard

Validate before calling

function assertSrc(src) { const isBlob = typeof Blob !== 'undefined' && src instanceof Blob; if (typeof src !== 'string' && !(src instanceof URL) && !isBlob) throw new TypeError('src must be a string, URL, or Blob'); }

Type guard

const isValidSrc = (v) => typeof v === 'string' || v instanceof URL || (typeof Blob !== 'undefined' && v instanceof Blob);

Try / catch

try { await separateVideoLayers({ src }); } catch (e) { if (e instanceof TypeError && e.message.includes('src must be a string, URL, or Blob')) { /* convert bytes to Blob or fix src */ } else throw e; }

Prevention

When it happens

Trigger: Passing an ArrayBuffer/Uint8Array of video bytes; passing undefined because the variable was misnamed; passing a File is fine (File extends Blob) but a plain object is not; passing a URL string built from non-string parts.

Common situations: Reading video into memory as bytes and assuming the API takes buffers; passing document.querySelector(...).src (DOM element instead of string); typed config from an unvalidated source.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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