heygen-com/hyperframes · error · Error
motionToGsap: invalid track "${track.property}" (values/time
Error message
motionToGsap: invalid track "${track.property}" (values/times mismatch) What it means
Thrown by buildTween when a MotionTrack is structurally invalid: either values.length < 2 (fewer than a start and end keyframe, so no tween exists) or times.length !== values.length (the time and value arrays disagree, so keyframe timing is ambiguous). motionToGsap cannot construct a GSAP keyframe sequence from such a track, and rather than emit a silent or misleading timeline it fails fast naming the offending property.
Source
Thrown at packages/core/src/figma/motionToGsap.ts:75
const value = track.values[i];
if (tPrev === undefined || tCur === undefined || value === undefined) continue;
const rawEase = track.ease[i - 1] ?? "linear";
const ease = resolveStepEase(rawEase, customEases, counter);
steps.push({ value, duration: (tCur - tPrev) * track.duration, ease });
}
return steps;
}
function buildTween(
track: MotionTrack,
selector: string,
customEases: CustomEaseRef[],
counter: CustomEaseCounter,
): GsapTween {
if (track.values.length < 2 || track.times.length !== track.values.length) {
throw new Error(`motionToGsap: invalid track "${track.property}" (values/times mismatch)`);
}
const initial = track.values[0];
if (initial === undefined) throw new Error(`motionToGsap: empty track "${track.property}"`);
return {
selector,
property: track.property,
initial,
steps: buildSteps(track, customEases, counter),
repeat: clampRepeat(track.repeat),
};
}
export function motionToGsap(doc: MotionDoc): TimelineSpec {
const customEases: CustomEaseRef[] = [];
const counter: CustomEaseCounter = { value: 0 };
const tweens = doc.tracks.map((track) => buildTween(track, doc.selector, customEases, counter));
return { timelineId: deriveId(doc.selector), tweens, customEases };View on GitHub (pinned to c2996c8626)
Solutions
- Filter out tracks with fewer than 2 keyframes before calling motionToGsap (static properties need no tween).
- Ensure times and values arrays are always the same length when building a MotionTrack.
- Inspect track.property in the error message to find which track is malformed, then fix its source.
- If the track came from figma's get_motion_context, re-fetch the snippet — a partial response can truncate arrays.
Example fix
// before — single keyframe track trips the guard
const track = { property: 'opacity', values: [1], times: [0], ease: [], duration: 1 };
// after — drop static tracks before translating
const animatable = doc.tracks.filter((t) => t.values.length >= 2 && t.times.length === t.values.length);
const spec = motionToGsap({ ...doc, tracks: animatable }); Defensive patterns
Strategy: validation
Validate before calling
import type { MotionTrack } from '.../figma/types';
export function isValidTrack(t: MotionTrack): boolean {
return t.values.length >= 2 && t.times.length === t.values.length;
}
// strip invalid tracks before motionToGsap
const validTracks = doc.tracks.filter(isValidTrack);
if (validTracks.length === 0) throw new Error('no animatable tracks');
const spec = motionToGsap({ ...doc, tracks: validTracks }); Type guard
import type { MotionTrack } from '.../figma/types';
export function isAnimatableTrack(t: MotionTrack): t is MotionTrack {
return t.values.length >= 2 && t.times.length === t.values.length;
} Prevention
- Filter single-keyframe tracks out of a MotionDoc before calling motionToGsap (they encode no motion).
- When building MotionTracks, push to times and values together so lengths stay in sync.
- If tracks come from figma's get_motion_context, validate them at the parser boundary.
When it happens
Trigger: A MotionTrack with values:[0.5] (single keyframe, no animation); values:[0,1] but times:[0] (mismatched lengths); a malformed motion.dev snippet parsed into a track with missing keyframes; hand-built MotionDoc where times/values arrays got out of sync.
Common situations: Parsing a figma motion snippet whose source had a single keyframe (no real animation); a refactored track builder that pushes to values but forgets times; an export tool emitting a 1-keyframe track for static properties instead of filtering it out.
Related errors
- motionToGsap: empty track "${track.property}"
- ref "${refInput}" has no node id — share a link with ?node-i
- all refs in one import must share a fileKey (batch is per-fi
- unsupported format "${raw}" — use one of ${FORMATS.join(", "
- ref "${refInput}" has no node id
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/005e9af2fc8ec457.
Report an issue: GitHub.