{"record":{"id":"3cb0a9c5b9a87644","repo":"Popmotion/popmotion","slug":"array-of-easing-functions-must-be-of-length-input","errorCode":null,"errorMessage":"Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.","messagePattern":"Array of easing functions must be of length `input\\.length - 1`, as it applies to the transitions \\*\\*between\\*\\* the defined values\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/popmotion/src/utils/interpolate.ts","lineNumber":130,"sourceCode":" *\n * mixColor(0.5) // 'rgba(128, 128, 128, 1)'\n * ```\n *\n * @public\n */\nexport function interpolate<T>(\n  input: number[],\n  output: T[],\n  { clamp: isClamp = true, ease, mixer }: InterpolateOptions<T> = {}\n) {\n  const inputLength = input.length;\n\n  invariant(\n    inputLength === output.length,\n    'Both input and output ranges must be the same length'\n  );\n\n  invariant(\n    !ease || !Array.isArray(ease) || ease.length === inputLength - 1,\n    'Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.'\n  );\n\n  // If input runs highest -> lowest, reverse both arrays\n  if (input[0] > input[inputLength - 1]) {\n    input = [].concat(input);\n    output = [].concat(output);\n    input.reverse();\n    output.reverse();\n  }\n\n  const mixers = createMixers(output, ease, mixer);\n\n  const interpolator =\n    inputLength === 2\n      ? fastInterpolate(input, mixers)\n      : slowInterpolate(input, mixers);","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Popmotion/popmotion/blob/adf681efd8568ada018ce68082dbd585f25c4c7d/packages/popmotion/src/utils/interpolate.ts#L112-L148","documentation":"When the `ease` option is an array of easing functions, `interpolate` requires exactly `input.length - 1` easers, because easings apply to the transitions *between* consecutive input stops, not to the stops themselves. `invariant` throws when the array is longer or shorter. A single easing function (non-array) is fine and is applied to all segments.","triggerScenarios":"`interpolate([0, 0.5, 1], ['0px','100px','200px'], { ease: [linear, linear, linear] })` (3 easers for 2 segments), or `{ ease: [linear] }` for a 3-stop input, or building the ease array dynamically and miscounting segments.","commonSituations":"Off-by-one confusion: developers assume one easing per input value instead of one per segment; copying an ease array from a config with a different number of keyframes; programmatic ease generation.","solutions":["Make `ease.length === input.length - 1` (one easing per segment between stops)","If you want the same easing everywhere, pass a single function instead of an array: `ease: easeInOut`","Count segments as `input.length - 1`, not `input.length`","Validate the ease array length against the input range before calling"],"exampleFix":"// before\ninterpolate([0, 0.5, 1], [0, 100, 200], { ease: [linear, linear, linear] });\n// after\ninterpolate([0, 0.5, 1], [0, 100, 200], { ease: [linear, linear] });","handlingStrategy":"validation","validationCode":"function validateEase(input, ease) {\n  if (Array.isArray(ease) && ease.length !== input.length - 1) {\n    throw new Error(`ease array must have ${input.length - 1} items (segments), got ${ease.length}`);\n  }\n}\n// call before interpolate(input, output, { ease })","typeGuard":"function isValidEaseArray<T>(input: number[], ease: unknown): ease is ((t: number) => T)[] {\n  return Array.isArray(ease) && ease.length === input.length - 1 && ease.every(fn => typeof fn === 'function');\n}","tryCatchPattern":null,"preventionTips":["Count segments as input.length - 1, never input.length","Prefer passing a single easing function when all segments share easing","Add a unit test asserting ease array length for programmatically built easings","When changing the number of keyframes, update the ease array in the same commit"],"tags":["interpolation","easing","array-length","validation"],"backgroundTag":"ease-array-length-mismatch","analyzedSha":"adf681efd8568ada018ce68082dbd585f25c4c7d","analyzedAt":"2026-09-02T10:01:11.645Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}