swc-project/swc · error · swc_css_parser::error::Error
Invalid @scope at-rule
Error message
Invalid @scope at-rule
What it means
The @scope at-rule prelude (its <scope-range>) has a fixed shape: '(<start>)', 'to (<end>)', or '(<start>) to (<end>)', where both bounds are parenthesized selector lists. The parser is at the start of the scope range and the current token is neither '(' nor the identifier 'to', so no valid scope range can begin and ErrorKind::InvalidScopeAtRule is returned.
Source
Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:2652
}
_ => {
if is_case_insensitive_ident!(self, "to") {
bump!(self);
self.input.skip_ws();
expect!(self, "(");
let end = self.parse()?;
expect!(self, ")");
return Ok(ScopeRange {
span: span!(self, span.lo),
scope_start: None,
scope_end: Some(end),
});
}
return Err(Error::new(span, ErrorKind::InvalidScopeAtRule));
}
}
}
}
View on GitHub (pinned to 5176682b65)
Solutions
- Wrap the scope start in parentheses: '@scope (div) { ... }'
- For both bounds use: '@scope (article) to (p) { ... }'
- For end-only scoping use the 'to' keyword with parens: '@scope to (footer) { ... }'
- If targeting draft-era examples, re-check them against the current @scope grammar
Example fix
/* before */
@scope div { ... }
/* after */
@scope (div) to (p) { ... } Defensive patterns
Strategy: validation
Validate before calling
// @scope prelude must be '(...)' / 'to (...)' / '(...) to (...)'
function scopePreludeOk(prelude) {
return /^$|^\(.*\)(\s+to\s+\(.*\))?$|^to\s+\(.*\)$/.test(prelude.trim());
} Try / catch
// JS
try { parse(css, opts); } catch (e) { if (/Invalid @scope/.test(e.message)) flagDraftSyntax('wrap @scope bounds in parentheses'); } Prevention
- Feature-detect @scope support and lint prelude shape
- Pin your team to the parenthesized grammar in examples and snippets
When it happens
Trigger: '@scope div { ... }' (unparenthesized scope start), '@scope to div { ... }' (missing parentheses around the end), or '@scope { ... }' is fine (EOF path) but '@scope ;;' / any junk token in the prelude triggers it.
Common situations: Authors writing @scope like a normal at-rule with a bare selector prelude (the parentheses are easy to forget); early adopters following draft syntax that changed to require parens; copy-pasting examples from articles that used an older syntax.
Related errors
- Expected function or '('
- Expected url or function
- Expected ident (exclude the keywords 'only', 'not', 'and', '
- Expected identifier value
- Expected '>' or '<' operators
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/0364f297ee1ad6d5.
Report an issue: GitHub.