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

Expected '>' or '<' operators

Error message

Expected '>' or '<' operators

What it means

Thrown while parsing media range syntax '(400px <= width)'. After the left value the parser accepts only '<' optionally followed by '=', or '>' optionally followed by '=' — i.e. <, <=, >, >=. Any other token at the comparison position raises ErrorKind::Expected("'>' or '<' operators").

Source

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

                }

                let right_comparison = match bump!(self) {
                    tok!("<") => {
                        if eat!(self, "=") {
                            MediaFeatureRangeComparison::Le
                        } else {
                            MediaFeatureRangeComparison::Lt
                        }
                    }
                    tok!(">") => {
                        if eat!(self, "=") {
                            MediaFeatureRangeComparison::Ge
                        } else {
                            MediaFeatureRangeComparison::Gt
                        }
                    }
                    _ => {
                        return Err(Error::new(
                            span,
                            ErrorKind::Expected("'>' or '<' operators"),
                        ));
                    }
                };

                self.input.skip_ws();

                let right = self.parse()?;

                self.input.skip_ws();

                expect!(self, ")");

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

View on GitHub (pinned to 5176682b65)

Solutions

  1. Use one of the four allowed operators: <, <=, >, >=
  2. For 'at least' semantics write @media (min-width: 600px) or @media (width >= 600px)
  3. If you generate queries, whitelist the operator set before emitting

Example fix

/* before */
@media (width = 600px) { }

/* after */
@media (width >= 600px) { }
Defensive patterns

Strategy: validation

Validate before calling

const OPS: [&str; 4] = ["<", "<=", ">", ">="];

fn range_operators_ok(css: &str) -> bool {
    for cap in css.split('(').skip(1) {
        let inner = cap.split(')').next().unwrap_or("");
        if inner.contains(':') {
            continue;
        }
        for tok in inner.split_whitespace() {
            if ["<", ">", "<=", ">="].contains(&tok.as_str()) {
                continue;
            }
            if tok.starts_with('=') || tok.contains("==") || tok.contains('~') {
                return false;
            }
        }
    }
    let _ = OPS;
    true
}

Type guard

fn is_range_operator_error(e: &swc_css_parser::error::Error) -> bool {
    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "'>' or '<' operators")
}

Try / catch

match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
    Ok(sheet) => handle(sheet),
    Err(err) if is_range_operator_error(&err) => {
        let (span, _) = *err.into_inner();
        hint_at_span(css, span, "media range syntax allows only < <= > >=; there is no '=' operator");
    }
    Err(err) => return Err(err.into()),
}

Prevention

When it happens

Trigger: '@media (width = 600px)' (single equals, which the media grammar does not have), '@media (width == 600px)', '@media (width ~ 600px)', '@media (width => 600px)'.

Common situations: Authors carrying '=' over from JS or from container queries in older draft syntax, transpilers/rewriters that normalize ':' to '=', and typos in hand-written level-4 range syntax.

Related errors


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