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

Expected left comparison operator should be equal right comp

Error message

Expected left comparison operator should be equal right comparison operator

What it means

Validation applied after parsing a range interval '(a OP1 name OP2 c)': both comparisons must point the same way — OP1 and OP2 must both come from {<, <=} or both from {>, >=}. Mixing directions (for example <= with >=) produces ErrorKind::Expected("left comparison operator should be equal right comparison operator"). The span is the whole feature, so the message plus span identifies which interval is inconsistent.

Source

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

                let is_valid_operator = match left_comparison {
                    MediaFeatureRangeComparison::Lt | MediaFeatureRangeComparison::Le
                        if right_comparison == MediaFeatureRangeComparison::Lt
                            || right_comparison == MediaFeatureRangeComparison::Le =>
                    {
                        true
                    }
                    MediaFeatureRangeComparison::Gt | MediaFeatureRangeComparison::Ge
                        if right_comparison == MediaFeatureRangeComparison::Gt
                            || right_comparison == MediaFeatureRangeComparison::Ge =>
                    {
                        true
                    }
                    _ => false,
                };

                if !is_valid_operator {
                    return Err(Error::new(
                        span,
                        ErrorKind::Expected(
                            "left comparison operator should be equal right comparison operator",
                        ),
                    ));
                }

                Ok(MediaFeature::RangeInterval(MediaFeatureRangeInterval {
                    span: span!(self, span.lo),
                    left: Box::new(left),
                    left_comparison,
                    name,
                    right_comparison,
                    right,
                }))
            }
            _ => Err(Error::new(span, ErrorKind::Expected("identifier value"))),
        }

View on GitHub (pinned to 5176682b65)

Solutions

  1. Make both operators the same direction: @media (400px <= width <= 700px)
  2. Or split the constraint into two conjoined features: @media (min-width: 400px) and (max-width: 700px)
  3. When generating intervals, derive the second operator from the first instead of a separate variable

Example fix

/* before */
@media (400px <= width >= 700px) { }

/* after */
@media (400px <= width <= 700px) { }
Defensive patterns

Strategy: validation

Validate before calling

fn interval_directions_ok(css: &str) -> bool {
    for cap in css.split('(').skip(1) {
        let inner = cap.split(')').next().unwrap_or("");
        let toks: Vec<&str> = inner.split_whitespace().collect();
        if toks.len() == 5 {
            let lt_family = |o: &str| o == "<" || o == "<=";
            let (a, b) = (toks[1], toks[3]);
            if ["<", "<=", ">", ">="].contains(&a) && ["<", "<=", ">", ">="].contains(&b) {
                if lt_family(a) != lt_family(b) {
                    return false;
                }
            }
        }
    }
    true
}

Type guard

fn is_interval_direction_error(e: &swc_css_parser::error::Error) -> bool {
    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "left comparison operator should be equal right comparison operator")
}

Try / catch

match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
    Ok(sheet) => handle(sheet),
    Err(err) if is_interval_direction_error(&err) => {
        let (span, _) = *err.into_inner();
        hint_at_span(css, span, "both operators in a range interval must point the same way, e.g. (400px <= width <= 700px)");
    }
    Err(err) => return Err(err.into()),
}

Prevention

When it happens

Trigger: '@media (400px <= width >= 700px)', '@media (400px < width >= 700px)' — any interval whose two operators have opposite directions.

Common situations: Hand-typed intervals where the second operator is flipped, and code generation that interpolates 'min' and 'max' operators independently so they can disagree.

Related errors


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