{"record":{"id":"c9f78b0816a3fed2","repo":"swc-project/swc","slug":"expected-ident-exclude-the-keywords-only-not","errorCode":null,"errorMessage":"Expected ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')","messagePattern":"Expected ident \\(exclude the keywords 'only', 'not', 'and', 'or' and 'layer'\\)","errorType":"validation","errorClass":"swc_css_parser::error::Error","httpStatus":null,"severity":"error","filePath":"crates/swc_css_parser/src/parser/at_rules/mod.rs","lineNumber":1447,"sourceCode":"        })\n    }\n}\n\nimpl<I> Parse<MediaType> for Parser<I>\nwhere\n    I: ParserInput,\n{\n    fn parse(&mut self) -> PResult<MediaType> {\n        match cur!(self) {\n            _ if !is_one_of_case_insensitive_ident!(self, \"not\", \"and\", \"or\", \"only\", \"layer\") => {\n                let name: Ident = self.parse()?;\n\n                Ok(MediaType::Ident(name))\n            }\n            _ => {\n                let span = self.input.cur_span();\n\n                Err(Error::new(\n                    span,\n                    ErrorKind::Expected(\n                        \"ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')\",\n                    ),\n                ))\n            }\n        }\n    }\n}\n\nimpl<I> Parse<MediaCondition> for Parser<I>\nwhere\n    I: ParserInput,\n{\n    fn parse(&mut self) -> PResult<MediaCondition> {\n        let start_pos = self.input.cur_span().lo;\n        let mut last_pos;\n        let mut conditions = Vec::new();","sourceCodeStart":1429,"sourceCodeEnd":1465,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_css_parser/src/parser/at_rules/mod.rs#L1429-L1465","documentation":"Thrown while parsing a <media-type> inside an @media (or @import ... media) prelude. The media type must be a plain identifier, and the five words 'only', 'not', 'and', 'or', 'layer' are grammar keywords that cannot serve as the type itself. When one of those keywords (or a non-ident token) sits where the media type is expected, ErrorKind::Expected(\"ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')\") is raised.","triggerScenarios":"'@media only { }' and '@media not { }' (modifier with no media type after it), '@media and { }', '@media layer { }' (using the cascade-layer keyword where a type belongs), or a query like '@media screen and only' where a keyword appears where the next type or condition must start.","commonSituations":"Dynamically composed media queries where an optional type segment was omitted and only/not is left dangling, migrations from CSS2 media types, and authors experimenting with @media layer(...) variants after learning cascade layers.","solutions":["Follow every only/not modifier with a real media type: @media only screen { }, @media not print { }","Remove dangling and/or keywords at the end of a query list item","Use @layer or @import ... layer() for cascade layers — 'layer' is never a media type","Prefer level-4 pure feature queries like @media (width >= 600px) when no media type is needed"],"exampleFix":"/* before */\n@media only {\n  .x { color: red; }\n}\n\n/* after */\n@media only screen {\n  .x { color: red; }\n}","handlingStrategy":"validation","validationCode":"const RESERVED: [&str; 5] = [\"only\", \"not\", \"and\", \"or\", \"layer\"];\n\nfn media_type_slot_ok(query: &str) -> bool {\n    let mut toks = query.split_whitespace();\n    while let Some(t) = toks.next() {\n        let t = t.trim_matches(|c| c == ',');\n        if t.eq_ignore_ascii_case(\"only\") || t.eq_ignore_ascii_case(\"not\") {\n            match toks.next() {\n                Some(next) if RESERVED.iter().any(|k| next.eq_ignore_ascii_case(k)) => return false,\n                Some(_) => {}\n                None => return false,\n            }\n        }\n    }\n    true\n}","typeGuard":"fn is_media_type_error(e: &swc_css_parser::error::Error) -> bool {\n    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == \"ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')\")\n}","tryCatchPattern":"match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {\n    Ok(sheet) => handle(sheet),\n    Err(err) if is_media_type_error(&err) => {\n        let (span, _) = *err.into_inner();\n        return Err(fixup_report(css, span, \"supply a real media type (screen, print, all) after only/not\"));\n    }\n    Err(err) => return Err(err.into()),\n}","preventionTips":["When composing '@media' strings, never emit only/not without the type that follows","Keep media types in an enum (screen, print, all, ...) instead of free strings","Prefer feature-only queries '@media (width >= X)' where no type is needed","Run stylelint's media-query rules on generated CSS"],"tags":["css","swc","parser","at-rules","media-query","syntax"],"backgroundTag":"css-media-query-syntax","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}