{"record":{"id":"a4d3665726345345","repo":"swc-project/swc","slug":"expected-or-operators","errorCode":null,"errorMessage":"Expected '>' or '<' operators","messagePattern":"Expected '>' or '<' operators","errorType":"validation","errorClass":"swc_css_parser::error::Error","httpStatus":null,"severity":"error","filePath":"crates/swc_css_parser/src/parser/at_rules/mod.rs","lineNumber":1818,"sourceCode":"                }\n\n                let right_comparison = match bump!(self) {\n                    tok!(\"<\") => {\n                        if eat!(self, \"=\") {\n                            MediaFeatureRangeComparison::Le\n                        } else {\n                            MediaFeatureRangeComparison::Lt\n                        }\n                    }\n                    tok!(\">\") => {\n                        if eat!(self, \"=\") {\n                            MediaFeatureRangeComparison::Ge\n                        } else {\n                            MediaFeatureRangeComparison::Gt\n                        }\n                    }\n                    _ => {\n                        return Err(Error::new(\n                            span,\n                            ErrorKind::Expected(\"'>' or '<' operators\"),\n                        ));\n                    }\n                };\n\n                self.input.skip_ws();\n\n                let right = self.parse()?;\n\n                self.input.skip_ws();\n\n                expect!(self, \")\");\n\n                let name = match center {\n                    MediaFeatureValue::Ident(ident) => MediaFeatureName::Ident(ident),\n                    _ => {\n                        return Err(Error::new(span, ErrorKind::Expected(\"identifier value\")));","sourceCodeStart":1800,"sourceCodeEnd":1836,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_css_parser/src/parser/at_rules/mod.rs#L1800-L1836","documentation":"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\").","triggerScenarios":"'@media (width = 600px)' (single equals, which the media grammar does not have), '@media (width == 600px)', '@media (width ~ 600px)', '@media (width => 600px)'.","commonSituations":"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.","solutions":["Use one of the four allowed operators: <, <=, >, >=","For 'at least' semantics write @media (min-width: 600px) or @media (width >= 600px)","If you generate queries, whitelist the operator set before emitting"],"exampleFix":"/* before */\n@media (width = 600px) { }\n\n/* after */\n@media (width >= 600px) { }","handlingStrategy":"validation","validationCode":"const OPS: [&str; 4] = [\"<\", \"<=\", \">\", \">=\"];\n\nfn range_operators_ok(css: &str) -> bool {\n    for cap in css.split('(').skip(1) {\n        let inner = cap.split(')').next().unwrap_or(\"\");\n        if inner.contains(':') {\n            continue;\n        }\n        for tok in inner.split_whitespace() {\n            if [\"<\", \">\", \"<=\", \">=\"].contains(&tok.as_str()) {\n                continue;\n            }\n            if tok.starts_with('=') || tok.contains(\"==\") || tok.contains('~') {\n                return false;\n            }\n        }\n    }\n    let _ = OPS;\n    true\n}","typeGuard":"fn is_range_operator_error(e: &swc_css_parser::error::Error) -> bool {\n    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == \"'>' or '<' operators\")\n}","tryCatchPattern":"match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {\n    Ok(sheet) => handle(sheet),\n    Err(err) if is_range_operator_error(&err) => {\n        let (span, _) = *err.into_inner();\n        hint_at_span(css, span, \"media range syntax allows only < <= > >=; there is no '=' operator\");\n    }\n    Err(err) => return Err(err.into()),\n}","preventionTips":["Whitelist comparison operators in query generators to {<, <=, >, >=}","Do not reuse JS comparison strings for CSS","Keep legacy (min-width: N) and range syntax in separate code paths","Lint sources for '==' inside @media conditions"],"tags":["css","swc","parser","at-rules","media-query","media-feature","range-syntax","syntax"],"backgroundTag":"css-media-feature-range-syntax","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}