swc-project/swc · error · Error

percentage, number, function (math functions) or ident (with

Error message

percentage, number, function (math functions) or ident (with 'none' value) token

What it means

Thrown by swc_css_parser when the FIRST channel of an rgb()/rgba() function starts with a token that is none of: percentage, number, math function (calc/min/max/...), or ident (crates/swc_css_parser/src/parser/values_and_units/mod.rs:429-441). The parser reports ErrorKind::Expected("percentage, number, function (math functions) or ident (with 'none' value) token") at the current token's span. The fallback arm only errors when has_variable_before is false, i.e. when no var()/env()/constant() has appeared in this function yet.

Source

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

                                    Ok(Some(ComponentValue::Function(parser.parse()?)))
                                }
                                tok!("ident") => {
                                    is_legacy_syntax = false;

                                    let ident: Box<Ident> = parser.parse()?;

                                    if ident.value.eq_ignore_ascii_case("none") {
                                        Ok(Some(ComponentValue::Ident(ident)))
                                    } else {
                                        Err(Error::new(
                                            ident.span,
                                            ErrorKind::Expected("'none' value of an ident token"),
                                        ))
                                    }
                                }
                                _ => {
                                    if !has_variable_before {
                                        Err(Error::new(
                                            parser.input.cur_span(),
                                            ErrorKind::Expected(
                                                "percentage, number, function (math functions) or \
                                                 ident (with 'none' value) token",
                                            ),
                                        ))
                                    } else {
                                        Ok(None)
                                    }
                                }
                            },
                            &mut has_variable,
                        )?;

                        if let Some(percentage_or_number_or_none) = percentage_or_number_or_none {
                            values.push(percentage_or_number_or_none);
                        }

View on GitHub (pinned to 5176682b65)

Solutions

  1. Use the correct channel types: 'rgb(255 0 0)' or 'rgb(100% 0% 0%)'; convert hex to 'rgb()' channels or keep the hex form '#fff'.
  2. Strip units/dimensions from channel values — rgb channels accept only plain numbers or percentages.
  3. Wrap dynamic or foreign content in var(): 'rgb(var(--x) 0 0)' bypasses the strict token check.
  4. Use the reported span (err.into_inner().0) to jump to the offending character in the stylesheet.

Example fix

/* before */
color: rgb(#fff 0 0);
color: rgb(255px 0 0);

/* after */
color: #fff;
color: rgb(255 0 0);
color: rgb(100% 0% 0%);
Defensive patterns

Strategy: try-catch

Validate before calling

fn rgb_channel_token_ok(arg: &str) -> bool {
    let a = arg.trim();
    !a.is_empty()
        && (a.parse::<f64>().is_ok()
            || a.ends_with('%')
            || a.eq_ignore_ascii_case("none")
            || a.starts_with("var(")
            || a.starts_with("env(")
            || ["calc(","min(","max(","clamp("].contains(&a.to_ascii_lowercase().as_str()))
}
// reject '#fff', '255px', '"x"', '' before they reach the parser

Type guard

fn looks_like_rgb_channel(tok_text: &str) -> bool {
    let t = tok_text.trim();
    t.chars().next().map_or(false, |c| c.is_ascii_digit() || c == '.' || c == '-' || c == '+')
        || t.ends_with('%')
        || t.eq_ignore_ascii_case("none")
        || t.starts_with("var(")
}

Try / catch

match swc_css_parser::parse_string::<Stylesheet>(css, config) {
    Ok(sheet) => sheet,
    Err(err) => {
        if matches!(&err.kind(), ErrorKind::Expected(m) if m.contains("percentage, number, function (math functions) or ident")) {
            // first rgb()/rgba() channel has a wrong token type; surface span and skip/repair the declaration
        }
        return Err(err.into());
    }
}

Prevention

When it happens

Trigger: parse_string on CSS like 'rgb(#fff 0 0)' (hash token), 'rgb("x" 0 0)' (string), 'rgb(, 0, 0)' (comma first), 'rgb(255px 0 0)' (dimension — not accepted for rgb channels), or 'rgb(/ 50%)'. All fall into the '_' arm at line 429 and fail at cur_span().

Common situations: Pasting hex colors into rgb(); CSS minifiers/design tools emitting dimensions where channels are expected; typos or truncated values after manual edits; generators emitting an empty first argument before a comma; older CSS round-tripped through preprocessors that wrote 'rgb(50%,0,0)' with stray units.

Related errors


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