swc-project/swc · error · Error

Expected number, function or percentage token

Error message

Expected number, function or percentage token

What it means

Thrown by Parse<CmykComponent> in swc_css_parser when a device-cmyk() component is expected but the current token is neither a number, a percentage, nor a function. Even when a function token is present, the impl additionally requires is_math_function(value) (calc/clamp/min/max/...), so var(--c) or rgb() in a component slot is rejected. The span points at the offending token.

Source

Thrown at crates/swc_css_parser/src/parser/values_and_units/mod.rs:2509

        match cur!(self) {
            tok!("number") => Ok(Hue::Number(self.parse()?)),
            tok!("dimension") => Ok(Hue::Angle(self.parse()?)),
            _ => {
                unreachable!()
            }
        }
    }
}

impl<I> Parse<CmykComponent> for Parser<I>
where
    I: ParserInput,
{
    fn parse(&mut self) -> PResult<CmykComponent> {
        if !is_one_of!(self, "number", "percentage", "function") {
            let span = self.input.cur_span();

            return Err(Error::new(
                span,
                ErrorKind::Expected("number, function or percentage token"),
            ));
        }

        match cur!(self) {
            tok!("number") => Ok(CmykComponent::Number(self.parse()?)),
            tok!("percentage") => Ok(CmykComponent::Percentage(self.parse()?)),
            Token::Function { value, .. } => {
                if !is_math_function(value) {
                    let span = self.input.cur_span();

                    return Err(Error::new(span, ErrorKind::Expected("math function token")));
                }

                Ok(CmykComponent::Function(self.parse()?))
            }
            _ => {

View on GitHub (pinned to 5176682b65)

Solutions

  1. Use numbers or percentages for cmyk components: 'device-cmyk(0 61% 87% 48%)'.
  2. Resolve var() references to concrete values before parsing, or wrap math in calc()/clamp() which are accepted functions.
  3. Validate each component against ^(\d+\.?\d*%?|calc\(.+\))$ before emitting device-cmyk().

Example fix

/* before */
a { color: device-cmyk(red 61% 87% 48%); }

/* after */
a { color: device-cmyk(0 61% 87% 48%); }
Defensive patterns

Strategy: validation

Validate before calling

const CMYK_COMPONENT = /^-?(\d+\.?\d*|\.\d+)%?$|^calc\(.+\)$/;
function isValidCmykComponent(v: string): boolean {
  return CMYK_COMPONENT.test(v.trim());
}

Type guard

fn is_cmyk_component_literal(v: &str) -> bool {
    let t = v.strip_suffix('%').unwrap_or(v);
    t.parse::<f64>().is_ok()
        || (v.starts_with("calc(") && v.ends_with(')'))
}

Try / catch

use swc_css_parser::error::ErrorKind;
if let Err(e) = parse_input::<Stylesheet>(src, opts) {
    if matches!(e.kind(), ErrorKind::Expected("number, function or percentage token")) {
        return Err(format!("bad device-cmyk component at {:?}", e.span()).into());
    }
    return Err(e.into());
}

Prevention

When it happens

Trigger: 'device-cmyk(red 61% 87% 48%)', 'device-cmyk(var(--c) 0 0 0)', 'device-cmyk(, 0 0 0)' (comma/EOF in a component slot), or a dimension like '10px' in a component position.

Common situations: Printer-oriented CSS generated from design tools that insert color keywords or CSS variables into device-cmyk() components, and empty components from buggy string joining.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/9f989bec4dfe8f62. Report an issue: GitHub.