swc-project/swc · error · swc_css_parser::error::Error
Expected id, class, attribute or pseudo-class selector
Error message
Expected id, class, attribute or pseudo-class selector
What it means
A subclass selector is one of exactly four things: '#id', '.class', '[attr]', or ':pseudo-class'. The parser was asked to produce a SubclassSelector but the current token is none of '#', '.', '[', ':'. In the compound-selector loop this position is pre-checked, so seeing this error usually means a code path (pseudo-class arguments, re-parse of fragments, direct use of the Parse impl) reached a subclass position with an unexpected token.
Source
Thrown at crates/swc_css_parser/src/parser/selectors/mod.rs:611
value,
})
}
}
impl<I> Parse<SubclassSelector> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<SubclassSelector> {
match cur!(self) {
tok!("#") => Ok(SubclassSelector::Id(self.parse()?)),
tok!(".") => Ok(SubclassSelector::Class(self.parse()?)),
tok!("[") => Ok(SubclassSelector::Attribute(self.parse()?)),
tok!(":") => Ok(SubclassSelector::PseudoClass(self.parse()?)),
_ => {
let span = self.input.cur_span();
return Err(Error::new(
span,
ErrorKind::Expected("id, class, attribute or pseudo-class selector"),
));
}
}
}
}
impl<I> Parse<IdSelector> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<IdSelector> {
let span = self.input.cur_span();
let text = match bump!(self) {
Token::Hash {
is_id, value, raw, ..
} => {View on GitHub (pinned to 5176682b65)
Solutions
- If you maintain calling code: re-check token cursor positioning before invoking subclass parsing; ensure is!('#'/"."/'['/':') guards wrap the call
- If hand CSS triggered it: look for a malformed pseudo-class or stray punctuation at the reported span and normalize the selector
- Prefer parsing whole selectors rather than re-parsed fragments where possible
Example fix
/* before (fragment re-parse misuse) */
parse_subclass("> a")
/* after */
parse_selector("> a") // parse at the right grammar level, or guard on the first token Defensive patterns
Strategy: type-guard
Validate before calling
// Only attempt subclass parsing when the token is one of the four openers
const subclassOpeners = new Set(['#', '.', '[', ':']);
function isSubclassStart(tok) { return subclassOpeners.has(tok); } Type guard
// Rust
fn is_subclass_start(t: &Token) -> bool {
matches!(t, Token::Hash { .. } | Token::Delim { value: '.' | '[' | ':' | '#', .. })
} Try / catch
// Rust: guard the call instead of relying on the error
if is_subclass_start(&cur) { let sel: SubclassSelector = parser.parse()?; } else { /* different grammar production */ } Prevention
- In tooling, always pair Parse::<SubclassSelector> with a token-kind check
- Parse selectors at the grammar level they belong to; do not re-parse fragments against a narrower production
When it happens
Trigger: Selector fragments re-parsed against subclass grammar where the token is a combinator/delimiter, e.g. tooling that calls Parse::<SubclassSelector> on '> a', or malformed pseudo-class argument lists that route into subclass parsing with the cursor on the wrong token.
Common situations: Tools built on swc_css_parser that slice and re-parse selector fragments (linters, CSS modules, minifiers) with an off-by-one token position; rarely hand-authored CSS, since the guarded loop normally reports the friendlier InvalidSelector instead.
Related errors
- Invalid selector
- Expected ident, '*' or '|' delim tokens
- Invalid attribute name
- failed to parse `{}` using lexical: {:?}
- Expected function or '('
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/d0ed95d8471114de.
Report an issue: GitHub.