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
- Pass an actual function: onProgress: (p) => console.log(p)
- Remove the onProgress key if you don't need progress updates
- 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
- Never round-trip callbacks through JSON
- Pass arrow functions directly at the call site
- Remove the key instead of passing a falsy non-function
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
- Output paths must be strings.
- outputs.${layer}.outputWritable must be a WritableStream.
- src must be a string, URL, or Blob.
- outputs must be an object.
- onModelLoadProgress must be a function.
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/834977f54d69d496.
Report an issue: GitHub.