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

  1. Pass easing: Easing.step1 so each segment steps at its midpoint: interpolate(t, [0,1], ["red","blue"], {easing: Easing.step1}).
  2. For multi-segment ranges, provide an array of Easing.step1 entries, one per segment.
  3. 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

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


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/e805f5bf46f356c9. Report an issue: GitHub.