mrdoob/three.js · error

unsupported interpolation for ${this.ValueTypeName} keyframe

Error message

unsupported interpolation for ${this.ValueTypeName} keyframe track named ${this.name}

What it means

Thrown by KeyframeTrack.setInterpolation() in the fatal branch: the requested interpolation constant has no factory method on this track subclass AND createInterpolant is undefined AND the requested interpolation is already the track's DefaultInterpolation (so there is nothing left to fall back to). Most unsupported-interpolation cases are non-fatal — the code warns and falls back to DefaultInterpolation — so this throw only occurs when even the default cannot produce an interpolant, meaning the track subclass is fundamentally incomplete.

Source

Thrown at src/animation/KeyframeTrack.js:224

				break;

		}

		if ( factoryMethod === undefined ) {

			const message = 'unsupported interpolation for ' +
				this.ValueTypeName + ' keyframe track named ' + this.name;

			if ( this.createInterpolant === undefined ) {

				// fall back to default, unless the default itself is messed up
				if ( interpolation !== this.DefaultInterpolation ) {

					this.setInterpolation( this.DefaultInterpolation );

				} else {

					throw new Error( message ); // fatal, in this case

				}

			}

			warn( 'KeyframeTrack:', message );
			return this;

		}

		this.createInterpolant = factoryMethod;

		return this;

	}

	/**
	 * Returns the current interpolation type.

View on GitHub (pinned to da05705fa3)

Solutions

  1. If you authored the track subclass, implement the relevant InterpolantFactoryMethod* (or override createInterpolant) so DefaultInterpolation resolves to a factory.
  2. If calling setInterpolation on a built-in discrete-only track (boolean/string), use InterpolateDiscrete rather than Linear/Smooth.
  3. If the throw comes from a built-in track, ensure you are on a current three.js version — a missing default factory on a stock track is a bug.

Example fix

// before — custom track with no factory; constructor's setInterpolation throws
class MyTrack extends KeyframeTrack {
  // no InterpolantFactoryMethod* defined, createInterpolant undefined
}
new MyTrack( 'x.value', [0,1], [0,1] ); // fatal

// after — provide a default interpolant factory
MyTrack.prototype.InterpolantFactoryMethodLinear =
  ( times, values, sample ) => new LinearInterpolant( times, values, sample );
Defensive patterns

Strategy: validation

Validate before calling

function safeSetInterpolation( track, interpolation ) {
  // Only request interpolations the track type can honour.
  const hasFactory = ( fn ) => typeof fn === 'function';
  const ok = interpolation === THREE.InterpolateDiscrete && hasFactory( track.InterpolantFactoryMethodDiscrete )
    || interpolation === THREE.InterpolateLinear && hasFactory( track.InterpolantFactoryMethodLinear )
    || interpolation === THREE.InterpolateSmooth && hasFactory( track.InterpolantFactoryMethodSmooth )
    || interpolation === THREE.InterpolateBezier && hasFactory( track.InterpolantFactoryMethodBezier );
  if ( ! ok ) throw new Error( `track cannot honour interpolation ${interpolation}` );
  track.setInterpolation( interpolation );
}

Type guard

function trackSupportsInterpolation( track, interpolation ) {
  const map = {
    [ THREE.InterpolateDiscrete ]: 'InterpolantFactoryMethodDiscrete',
    [ THREE.InterpolateLinear ]: 'InterpolantFactoryMethodLinear',
    [ THREE.InterpolateSmooth ]: 'InterpolantFactoryMethodSmooth',
    [ THREE.InterpolateBezier ]: 'InterpolantFactoryMethodBezier',
  };
  return typeof track[ map[ interpolation ] ] === 'function';
}

Try / catch

try {
  track.setInterpolation( THREE.InterpolateSmooth );
} catch ( err ) {
  if ( /unsupported interpolation/.test( err.message ) ) {
    console.warn( 'smooth unsupported; falling back to discrete' );
    track.setInterpolation( THREE.InterpolateDiscrete );
  } else throw err;
}

Prevention

When it happens

Trigger: Subclassing KeyframeTrack without defining InterpolantFactoryMethodLinear/Smooth/Discrete/Bezier and without overriding createInterpolant, then constructing it (the constructor calls setInterpolation with DefaultInterpolation). Calling setInterpolation(InterpolateSmooth) on a track type (like StringKeyframeTrack or BooleanKeyframeTrack) that only supports InterpolateDiscrete after the default-discrete fallback already failed to find a factory.

Common situations: Writing a custom KeyframeTrack subclass and forgetting to provide an interpolant factory. Downgrading a track's interpolation to one its value type cannot honour (e.g. smooth-interpolating a boolean track) in an environment where the discrete factory was also not wired.

Related errors


AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12). Data as JSON: /api/errors/169cafc0008ac208. Report an issue: GitHub.