necolas/react-native-web · error · Error

Invalid CSS keyframes type: ${typeof keyframesValue}

Error message

Invalid CSS keyframes type: ${typeof keyframesValue}

What it means

processKeyframesValue compiles StyleSheet keyframes objects into CSS @keyframes. A keyframes value of type 'number' cannot be interpreted as keyframes, so the compiler throws. It signals that a non-keyframes object was passed where StyleSheet keyframes were expected.

Source

Thrown at packages/react-native-web/src/exports/StyleSheet/compiler/index.js:496

        const rule = keyframes[stepName];
        const block = createDeclarationBlock(rule);
        return `${stepName}${block}`;
      })
      .join('') +
    '}';

  const rules = prefixes.map((prefix) => {
    return `@${prefix}keyframes ${identifier}${steps}`;
  });
  return [identifier, rules];
}

/**
 * Create CSS keyframes rules and names from a StyleSheet keyframes object.
 */
function processKeyframesValue(keyframesValue) {
  if (typeof keyframesValue === 'number') {
    throw new Error(`Invalid CSS keyframes type: ${typeof keyframesValue}`);
  }

  const animationNames = [];
  const rules = [];
  const value = Array.isArray(keyframesValue)
    ? keyframesValue
    : [keyframesValue];

  value.forEach((keyframes) => {
    if (typeof keyframes === 'string') {
      // Support external animation libraries (identifiers only)
      animationNames.push(keyframes);
    } else {
      // Create rules for each of the keyframes
      const [identifier, keyframesRules] = createKeyframes(keyframes);
      animationNames.push(identifier);
      rules.push(...keyframesRules);
    }

View on GitHub (pinned to a9de220ba9)

Solutions

  1. Set animationName to a StyleSheet.keyframes({...}) result or a keyframes object, not a number.
  2. Check the value bound to keyframesValue at runtime — fix whatever variable resolves to a number.
  3. Use animation-duration styles for timing numbers instead of the keyframes slot.

Example fix

// before
StyleSheet.create({ anim: { animationName: 300, animationDuration: '2s' } })
// after
const kf = StyleSheet.keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
StyleSheet.create({ anim: { animationName: kf, animationDuration: '2s' } })
Defensive patterns

Strategy: type-guard

Validate before calling

function assertKeyframes(v) {
  const ok = v && (Array.isArray(v) ? v.length > 0 : typeof v === 'object');
  if (!ok) throw new TypeError('animationName/keyframes must be a keyframes object, got: ' + typeof v);
}

Type guard

const isKeyframesValue = (v) => v != null && (Array.isArray(v) || (typeof v === 'object' && typeof v !== 'number'));

Try / catch

try { const styles = StyleSheet.create({ anim: { animationName: kf } }); } catch (e) { if (/Invalid CSS keyframes/.test(e.message)) console.error('keyframes must be an object/array, not a number'); }

Prevention

When it happens

Trigger: Passing a number as a keyframes value to StyleSheet.create or animationName composition, e.g. animationName: 300 or a numeric variable instead of a keyframes object/array.

Common situations: Confusing animationDuration (number) with animationName (keyframes); a dynamic value that resolves to a number; typos where a style value was pasted into the keyframes slot.

Related errors


AI-assisted analysis of necolas/react-native-web@a9de220ba9 (2026-09-01). Data as JSON: /api/errors/02dd7b43249362de. Report an issue: GitHub.