swc-project/swc · error · swc_css_parser::error::Error
Expected function or '('
Error message
Expected function or '(' What it means
Thrown by swc_css_parser while parsing a <general-enclosed> operand, most visibly in an @supports prelude (and in the media-query fallback chain). After a logical keyword, the grammar only accepts a function token such as selector(...), media(...) or supports(...), or a parenthesized block whose first non-whitespace component value is an identifier. When the current token is neither a function nor '(', the parser returns ErrorKind::Expected("function or '('") with the span of the offending token and the at-rule prelude fails to parse.
Source
Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:1282
),
));
}
}
}
if !found_ident {
return Err(Error::new(
block.span,
ErrorKind::Expected("ident at first position in <general-enclosed>"),
));
}
Ok(GeneralEnclosed::SimpleBlock(block))
}
_ => {
let span = self.input.cur_span();
Err(Error::new(span, ErrorKind::Expected("function or '('")))
}
}
}
}
impl<I> Parse<DocumentPreludeMatchingFunction> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<DocumentPreludeMatchingFunction> {
match cur!(self) {
tok!("url") => Ok(DocumentPreludeMatchingFunction::Url(self.parse()?)),
Token::Function {
value: function_name,
..
} => {
if matches_eq_ignore_ascii_case!(function_name, "url", "src") {
Ok(DocumentPreludeMatchingFunction::Url(self.parse()?))View on GitHub (pinned to 5176682b65)
Solutions
- Put every operand of the condition in parentheses: @supports (display: grid) and (display: flex) { }
- Use the special functions for non-declaration queries: @supports selector(a > b), @supports media(...), @supports supports(...)
- Delete stray tokens after and/or/not in the @supports prelude
- Use the reported span: it marks exactly the token that is neither a function nor '(' — search that offset in your generated CSS
Example fix
/* before */
@supports (display: grid) or 5px {
.grid { display: grid; }
}
/* after */
@supports (display: grid) or (display: flex) {
.grid { display: grid; }
} Defensive patterns
Strategy: try-catch
Validate before calling
fn supports_operands_ok(css: &str) -> bool {
let prelude = css.split_once('{').map_or(css, |(p, _)| p);
let body = prelude.splitn(2, "supports").nth(1).unwrap_or("");
for tok in body.split_whitespace() {
let t = tok.trim_matches(|c| c == ',');
if t.eq_ignore_ascii_case("and") || t.eq_ignore_ascii_case("or") || t.eq_ignore_ascii_case("not") {
continue;
}
if !(t.starts_with('(') || t.ends_with(')')) {
return false;
}
}
true
} Type guard
fn is_supports_operand_error(e: &swc_css_parser::error::Error) -> bool {
matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "function or '('")
} Try / catch
let mut errors = Vec::new();
match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
Ok(sheet) => handle(sheet),
Err(err) if is_supports_operand_error(&err) => {
let (span, _) = *err.into_inner();
reject_css_with_location(css, span, "each @supports operand must be (...) or a function like selector(...)");
}
Err(err) => return Err(err.into()),
} Prevention
- Lint supports preludes with stylelint before passing CSS to swc
- When concatenating condition fragments, always append '(...)' together with the keyword
- Keep fixture tests covering each @supports form you emit
- Reject user-authored at-rules that are not on an allowlist
When it happens
Trigger: A supports condition continued with a non-function, non-parenthesized token: '@supports (display: grid) or 5px { }', '@supports "foo" { }', '@supports 7 { }', a stray hash/number after and/or/not, or a truncated prelude where the leading '(' of the next operand was dropped (common with string concatenation of conditions).
Common situations: Hand-written @supports rules with typos, template engines or CSS-in-JS glue emitting partial condition fragments, preprocessing steps that strip or insert tokens when rewriting supports queries, and CSS copied from specs/demos that got truncated in transit.
Related errors
- Expected url or function
- Expected ident (exclude the keywords 'only', 'not', 'and', '
- Expected identifier value
- Expected '>' or '<' operators
- Expected number, ident, dimension or function token
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/98d19252ae253e05.
Report an issue: GitHub.