Popmotion/popmotion · warning
Complex values '${origin}' and '${target}' too different to
Error message
Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition. What it means
`mixComplex` parses complex strings (e.g. box-shadows, gradients, transform strings) into arrays of numbers and colors. If the two values don't have the same structure — same color types and same quantity of numbers/colors — interpolation is impossible, so it emits this `warning` (not a throw) and falls back to an instant transition: before p>0 the origin is shown, after that the target.
Source
Thrown at packages/popmotion/src/utils/mix-complex.ts:100
origin: string | number,
target: string | number
): MixComplex => {
const template = complex.createTransformer(target)
const originStats = analyse(origin)
const targetStats = analyse(target)
const canInterpolate =
originStats.numHSL === targetStats.numHSL &&
originStats.numRGB === targetStats.numRGB &&
originStats.numNumbers >= targetStats.numNumbers
if (canInterpolate) {
return pipe(
mixArray(originStats.parsed, targetStats.parsed),
template
) as MixComplex
} else {
warning(
true,
`Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`
)
return (p: number) => `${p > 0 ? target : origin}`
}
}
View on GitHub (pinned to adf681efd8)
Solutions
- Make both strings structurally identical: same color format and same count of numbers/colors
- Normalize all colors to one format (e.g. convert hex to rgba) before animating
- If an instant jump is unacceptable, animate the components separately via `animate` on individual values
- Heed the warning in the console — the transition is currently not interpolating smoothly
Example fix
// before animate boxShadow: '0px 2px 4px rgba(0,0,0,0.5)' -> '1px 1px 2px #000000' // after animate boxShadow: '0px 2px 4px rgba(0,0,0,0.5)' -> '1px 1px 2px rgba(0,0,0,1)'
Defensive patterns
Strategy: fallback
Validate before calling
function complexShapesMatch(origin, target) {
const nums = s => (s.match(/-?\d*\.?\d+/g) || []).length;
const colors = s => (s.match(/(#[0-9a-f]{3,8}|rgba?\([^)]*\)|hsla?\([^)]*\))/gi) || []).length;
return nums(origin) === nums(target) && colors(origin) === colors(target);
}
// if false, normalize the strings before animating Try / catch
// The library already falls back to an instant jump; add your own guard:
const mixer = complexShapesMatch(origin, target)
? mixComplex(origin, target)
: (() => { console.warn('Structures differ; animating a proxy instead'); return mixComplex(normalize(origin), normalize(target)); })(); Prevention
- Author paired complex values (box-shadow, gradient, transform) from a single template so structures always match
- Standardize color format (rgba everywhere) in tokens and CSS output
- Listen for the console warning in dev — it signals a non-animated jump
- If structures can't be matched, animate individual numeric properties instead of the whole string
When it happens
Trigger: `mixComplex('0px 0px 0px rgba(0,0,0,0.2)', '1px 2px 3px #000000')` (mixing rgba with hex), strings with different numbers of numeric values, or animating between values where one side has an extra component.
Common situations: Animating box-shadow or filter strings authored in inconsistent formats; values pulled from CSS/design tokens where one uses hex and the other rgba; hand-edited keyframe values.
Related errors
- Both input and output ranges must be the same length
- Array of easing functions must be of length `input.length -
AI-assisted analysis of Popmotion/popmotion@adf681efd8 (2026-09-02).
Data as JSON: /api/errors/236413de95bc92dc.
Report an issue: GitHub.