remotion-dev/remotion · error · TypeError
Non-numeric strings can only be interpolated using Easing.st
Error message
Non-numeric strings can only be interpolated using Easing.step1
What it means
Thrown by interpolateDiscreteString when outputRange contains non-numeric strings (e.g. colors, URLs, arbitrary tokens that parseStringInterpolationValue cannot treat as scale/translate/rotate) and at least one segment's easing is not Easing.step1. Non-numeric strings cannot be numerically interpolated, so they must step instantly at segment boundaries.
Source
Thrown at packages/core/src/interpolate.ts:898
outputRange: readonly string[];
options: InterpolateOptions | undefined;
}): string => {
if (inputRange.length === 1) {
return outputRange[0];
}
for (
let segmentIndex = 0;
segmentIndex < inputRange.length - 1;
segmentIndex++
) {
if (
resolveEasingForSegment({
easing: options?.easing,
segmentIndex,
}) !== Easing.step1
) {
throw new TypeError(
'Non-numeric strings can only be interpolated using Easing.step1',
);
}
}
const posterizedInput =
options?.posterize === undefined
? input
: Math.floor(input / options.posterize) * options.posterize;
const inputMin = inputRange[0];
const inputMax = inputRange[inputRange.length - 1];
let resolvedInput = posterizedInput;
if (resolvedInput < inputMin) {
if (options?.extrapolateLeft === 'identity') {
throw new TypeError(
'extrapolateLeft: "identity" is not supported for non-numeric strings',
);View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Pass easing: Easing.step1 so each segment steps at its midpoint: interpolate(t, [0,1], ["red","blue"], {easing: Easing.step1}).
- For multi-segment ranges, provide an array of Easing.step1 entries, one per segment.
- If you wanted smooth color animation, interpolate numeric channels (RGB) yourself or use a numeric outputRange.
Example fix
// before
interpolate(t, [0, 1], ["red", "blue"]);
// after
interpolate(t, [0, 1], ["red", "blue"], {easing: Easing.step1}); Defensive patterns
Strategy: validation
Validate before calling
import {Easing} from 'remotion';
function isDiscreteStringRange(outputRange: readonly (string | number)[]): boolean {
return outputRange.some((o) => typeof o === 'string')
&& outputRange.some((o) => {
if (typeof o !== 'string') return false;
try {
// re-implementation of parseStringInterpolationValue's accept check
const parts = o.trim().split(/\s+/);
return parts.some((p) => !/^([+-]?(?:\d+\.?\d*|\.\d+))([a-zA-Z%]+)?$/.test(p)
&& !/^(left|right|top|bottom|center)$/i.test(p));
} catch {
return true;
}
});
}
if (isDiscreteStringRange(outputRange)) {
const easings = options?.easing;
const allStep = Array.isArray(easings)
? easings.every((e) => e === Easing.step1)
: easings === undefined || easings === Easing.step1;
if (!allStep) throw new Error('Non-numeric strings require easing: Easing.step1');
} Prevention
- For color or arbitrary-token outputRange, always pass {easing: Easing.step1}.
- For multi-segment discrete ranges, pass an Easing.step1 array sized inputRange.length - 1.
- If smooth motion is required, interpolate numeric channels instead of literal strings.
When it happens
Trigger: interpolate(t, [0, 1], ["red", "blue"]) with no options, or with easing: Easing.linear; or multi-segment ["a","b","c"] where any segment lacks Easing.step1. Remotion falls back to discrete interpolation only when numeric interpolation is impossible.
Common situations: Animating between colors, display values ("block"/"none"), or content strings and forgetting that discrete steps require Easing.step1; using a default easing with a string outputRange.
Related errors
- bezier x values must be in [0, 1] range
- extrapolateLeft: "identity" is not supported for non-numeric
- extrapolateRight: "identity" is not supported for non-numeri
- invalid color string ${color} provided
- input can not be undefined
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/e805f5bf46f356c9.
Report an issue: GitHub.