remotion-dev/remotion · error · TypeError

onProgress must be a function.

Error message

onProgress must be a function.

What it means

validateOptions for separateVideoLayers() verifies the optional onProgress callback is actually a function; since progress reporting is invoked during the long separation run, a non-function value would crash later and is rejected during option validation.

Source

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

	resolveVideoMattingQuality(options.videoBitrate ?? 'very-high');
	resolveVideoMattingQuality(options.audioBitrate ?? 'medium');

	if (
		options.keyframeIntervalInSeconds !== undefined &&
		(!Number.isFinite(options.keyframeIntervalInSeconds) ||
			options.keyframeIntervalInSeconds <= 0)
	) {
		throw new TypeError(
			'keyframeIntervalInSeconds must be a positive finite number.',
		);
	}

	if (
		options.onProgress !== undefined &&
		typeof options.onProgress !== 'function'
	) {
		throw new TypeError('onProgress must be a function.');
	}

	if (
		options.onModelLoadProgress !== undefined &&
		typeof options.onModelLoadProgress !== 'function'
	) {
		throw new TypeError('onModelLoadProgress must be a function.');
	}
};

const makeInput = (src: string | URL | Blob): Input => {
	const source =
		typeof src === 'string' || src instanceof URL
			? new UrlSource(src)
			: new BlobSource(src);

	return new Input({formats: ALL_FORMATS, source});
};

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Pass an actual function: onProgress: (p) => console.log(p)
  2. Remove the onProgress key if you don't need progress updates
  3. If options come from JSON/config, attach callbacks after parsing

Example fix

// before
await separateVideoLayers({ src, outputs, onProgress: config.onProgress }); // undefined-ish object from JSON
// after
await separateVideoLayers({ src, outputs, onProgress: (progress) => console.log(Math.round(progress * 100) + '%') });
Defensive patterns

Strategy: type-guard

Validate before calling

if (onProgress !== undefined && typeof onProgress !== 'function') throw new TypeError('onProgress must be a function');

Type guard

const isFunction = (v) => typeof v === 'function';

Try / catch

try { await separateVideoLayers(opts); } catch (e) { if (e instanceof TypeError && e.message.includes('onProgress must be a function')) { /* attach a real callback */ } else throw e; }

Prevention

When it happens

Trigger: Passing onProgress: true, an object, a stringified function, or a variable that is undefined-but-assigned (e.g. a JSON-parsed config where functions cannot survive serialization).

Common situations: Loading options from JSON (functions don't serialize); passing console.log.bind result incorrectly; typing the value into a config file.

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/834977f54d69d496. Report an issue: GitHub.