swc-project/swc · error · swc_css_parser::error::Error

Expected identifier value

Error message

Expected identifier value

What it means

Thrown while parsing a boolean media feature — the form '(name)' with no colon or comparison. After parsing the single value inside the parentheses the parser sees ')' and requires that value to have been an identifier (the feature name). If it parsed as a number, dimension, or function instead, ErrorKind::Expected("identifier value") is raised with the span of the opening parenthesis.

Source

Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:1733

                    span: span!(self, span.lo),
                    name,
                }));
            }
            _ => {}
        };

        let left = self.parse()?;

        self.input.skip_ws();

        match cur!(self) {
            tok!(")") => {
                bump!(self);

                let name = match left {
                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),
                    _ => {
                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
                    }
                };

                Ok(MediaFeature::Boolean(MediaFeatureBoolean {
                    span: span!(self, span.lo),
                    name,
                }))
            }
            tok!(":") => {
                bump!(self);

                self.input.skip_ws();

                let name = match left {
                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),
                    _ => {
                        return Err(Error::new(span, ErrorKind::Expected("identifier value")));
                    }

View on GitHub (pinned to 5176682b65)

Solutions

  1. Name the feature in boolean context: @media (hover), @media (width)
  2. Use range syntax for value comparisons: @media (width >= 200px)
  3. Use the classic plain form: @media (min-width: 200px)
  4. Remember custom '--*' features are only valid in boolean context and still need the leading ident

Example fix

/* before */
@media (200px) {
  .a { color: red; }
}

/* after */
@media (width >= 200px) {
  .a { color: red; }
}
Defensive patterns

Strategy: validation

Validate before calling

fn boolean_features_ok(css: &str) -> bool {
    // best-effort: every parenthesized (...) with no ':' and no comparison must be a bare ident
    let bytes = css.as_bytes();
    let mut i = 0;
    while let Some(open) = css[i..].find('(') {
        let start = i + open;
        if let Some(close_rel) = css[start + 1..].find(')') {
            let inner = &css[start + 1..start + 1 + close_rel];
            let has_op = [":", "<", ">"].iter().any(|o| inner.contains(o));
            if !has_op && !inner.starts_with("--") {
                let ok = inner.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_');
                if !ok || inner.parse::<f64>().is_ok() {
                    return false;
                }
            }
            i = start + 1 + close_rel;
        } else {
            break;
        }
        let _ = bytes;
    }
    true
}

Type guard

fn is_identifier_value_error(e: &swc_css_parser::error::Error) -> bool {
    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "identifier value")
}

Try / catch

match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
    Ok(sheet) => handle(sheet),
    Err(err) if is_identifier_value_error(&err) => {
        let (span, _) = *err.into_inner();
        hint_at_span(css, span, "boolean media features need a name like (width), not a value; use (width >= N) for comparisons");
    }
    Err(err) => return Err(err.into()),
}

Prevention

When it happens

Trigger: '@media (200px)' (a length where a feature name belongs), '@media (calc(10px + 2em))' (math function as a boolean feature), '@media (5)' — any boolean-context paren whose content is not a plain ident.

Common situations: Authors writing value-only shorthand expecting it to mean min-width, CSS generated from design tokens that interpolates raw sizes, and copy-paste of range syntax with the comparison operator accidentally removed.

Related errors


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