swc-project/swc · error · swc_css_parser::error::Error
Expected ident (exclude the keywords 'only', 'not', 'and', '
Error message
Expected ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')
What it means
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.
Source
Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:1447
})
}
}
impl<I> Parse<MediaType> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<MediaType> {
match cur!(self) {
_ if !is_one_of_case_insensitive_ident!(self, "not", "and", "or", "only", "layer") => {
let name: Ident = self.parse()?;
Ok(MediaType::Ident(name))
}
_ => {
let span = self.input.cur_span();
Err(Error::new(
span,
ErrorKind::Expected(
"ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')",
),
))
}
}
}
}
impl<I> Parse<MediaCondition> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<MediaCondition> {
let start_pos = self.input.cur_span().lo;
let mut last_pos;
let mut conditions = Vec::new();View on GitHub (pinned to 5176682b65)
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
Example fix
/* before */
@media only {
.x { color: red; }
}
/* after */
@media only screen {
.x { color: red; }
} Defensive patterns
Strategy: validation
Validate before calling
const RESERVED: [&str; 5] = ["only", "not", "and", "or", "layer"];
fn media_type_slot_ok(query: &str) -> bool {
let mut toks = query.split_whitespace();
while let Some(t) = toks.next() {
let t = t.trim_matches(|c| c == ',');
if t.eq_ignore_ascii_case("only") || t.eq_ignore_ascii_case("not") {
match toks.next() {
Some(next) if RESERVED.iter().any(|k| next.eq_ignore_ascii_case(k)) => return false,
Some(_) => {}
None => return false,
}
}
}
true
} Type guard
fn is_media_type_error(e: &swc_css_parser::error::Error) -> bool {
matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer')")
} Try / catch
match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
Ok(sheet) => handle(sheet),
Err(err) if is_media_type_error(&err) => {
let (span, _) = *err.into_inner();
return Err(fixup_report(css, span, "supply a real media type (screen, print, all) after only/not"));
}
Err(err) => return Err(err.into()),
} Prevention
- 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
When it happens
Trigger: '@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.
Common situations: 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.
Related errors
- Expected identifier value
- Expected '>' or '<' operators
- Expected number, ident, dimension or function token
- Expected function or '('
- Expected url or function
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/c9f78b0816a3fed2.
Report an issue: GitHub.