{"record":{"id":"6310aeececbaf4e3","repo":"heygen-com/hyperframes","slug":"motiontogsap-empty-track-track-property","errorCode":null,"errorMessage":"motionToGsap: empty track \"${track.property}\"","messagePattern":"motionToGsap: empty track \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/figma/motionToGsap.ts","lineNumber":78,"sourceCode":"    const rawEase = track.ease[i - 1] ?? \"linear\";\n    const ease = resolveStepEase(rawEase, customEases, counter);\n    steps.push({ value, duration: (tCur - tPrev) * track.duration, ease });\n  }\n\n  return steps;\n}\n\nfunction buildTween(\n  track: MotionTrack,\n  selector: string,\n  customEases: CustomEaseRef[],\n  counter: CustomEaseCounter,\n): GsapTween {\n  if (track.values.length < 2 || track.times.length !== track.values.length) {\n    throw new Error(`motionToGsap: invalid track \"${track.property}\" (values/times mismatch)`);\n  }\n  const initial = track.values[0];\n  if (initial === undefined) throw new Error(`motionToGsap: empty track \"${track.property}\"`);\n\n  return {\n    selector,\n    property: track.property,\n    initial,\n    steps: buildSteps(track, customEases, counter),\n    repeat: clampRepeat(track.repeat),\n  };\n}\n\nexport function motionToGsap(doc: MotionDoc): TimelineSpec {\n  const customEases: CustomEaseRef[] = [];\n  const counter: CustomEaseCounter = { value: 0 };\n  const tweens = doc.tracks.map((track) => buildTween(track, doc.selector, customEases, counter));\n  return { timelineId: deriveId(doc.selector), tweens, customEases };\n}\n","sourceCodeStart":60,"sourceCodeEnd":95,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/figma/motionToGsap.ts#L60-L95","documentation":"Thrown by buildTween as a defensive guard after the length check passes: track.values[0] is undefined despite values.length >= 2. With a dense array and values.length >= 2 this is unreachable, so in practice it fires only for a sparse/holey array (e.g. [undefined, 1]) — a malformed MotionTrack where the first keyframe slot exists but holds no value. It prevents GSAP from receiving an undefined initial value and emitting a broken tween deep in the pipeline.","triggerScenarios":"A MotionTrack whose values array is sparse ([undefined, 0.5] or values[0] deleted); a builder that allocated array length then failed to populate index 0; JSON deserialisation producing holes after filtering.","commonSituations":"A motion-snippet parser that does `values[i] = ...` starting at i=1; an array built with `new Array(n)` whose slots were never all assigned; an object spread that dropped the first value.","solutions":["Build the values array with push()/literal form so no holes appear.","Validate the track before motionToGsap: values.every(v => v !== undefined).","Inspect the source of the track (figma motion snippet parser) for an off-by-one in array assignment."],"exampleFix":"// before — off-by-one leaves index 0 undefined\nconst values = new Array(2);\nfor (let i = 1; i <= 2; i++) values[i] = i * 0.5; // values[0] is a hole\n\n// after — assign from 0, or build with a literal\nconst values = [0, 0.5, 1];","handlingStrategy":"validation","validationCode":"import type { MotionTrack } from '.../figma/types';\nexport function isDenseTrack(t: MotionTrack): boolean {\n  return t.values.length >= 2 && t.values.every((v) => v !== undefined);\n}\nif (!isDenseTrack(track)) throw new Error(`track ${track.property} has holes`);","typeGuard":"import type { MotionTrack } from '.../figma/types';\nexport function isDenseAnimatableTrack(t: MotionTrack): t is MotionTrack {\n  return t.values.length >= 2\n    && t.times.length === t.values.length\n    && t.values.every((v) => v !== undefined);\n}","tryCatchPattern":null,"preventionTips":["Build value arrays with literals or push(), never new Array(n) + index assignment that can leave holes.","Validate array density at the boundary where MotionTracks enter your code.","Watch for off-by-one loops that assign starting at index 1."],"tags":["figma","motion","gsap","validation","defensive"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}