swc-project/swc · error · swc_css_parser::error::Error
Unexpected characters in ID selector
Error message
Unexpected characters in ID selector
What it means
CSS tokenizes '#...' as a Hash token with is_id=true only when the remainder would form a valid identifier; otherwise (e.g. '#123') is_id=false and it is not usable as an ID selector. The parser consumed a Hash token whose is_id flag is false, meaning the text after '#' contains characters that cannot start an identifier (digits, or unescaped specials), so it rejects it as an ID selector.
Source
Thrown at crates/swc_css_parser/src/parser/selectors/mod.rs:631
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, ..
} => {
if !is_id {
return Err(Error::new(
span,
ErrorKind::Unexpected("characters in ID selector"),
));
}
Ident {
span,
value,
raw: Some(raw),
}
}
_ => {
unreachable!()
}
};
Ok(IdSelector {
span: span!(self, span.lo),View on GitHub (pinned to 5176682b65)
Solutions
- Escape the first digit with its hex escape and a space: '#\31 23abc' (escape for '1' plus separating space)
- Prefer a class selector '.item-123' for machine-generated names
- When generating selectors from IDs, run them through an identifier-escaping helper (CSS.escape in JS)
Example fix
/* before */
#1st { color: red; }
/* after */
#\31 st { color: red; } /* or rename the id to a letter-first value */ Defensive patterns
Strategy: type-guard
Validate before calling
// IDs usable as selectors must be ident-shaped after '#'
function isCssIdent(s) { return /^--?[A-Za-z_][\w-]*$/.test(s) || /^\[0-9a-fA-F]{1,6} /.test(s); } Type guard
// JS (browser/helpers)
function idIsSelectable(id) { return /^[A-Za-z_-][\w-]*$/.test(id); }
// escape otherwise: CSS.escape(id) Try / catch
// JS
const sel = idIsSelectable(id) ? `#${id}` : `#${CSS.escape ? CSS.escape(id) : escapeIdent(id)}`; Prevention
- Run CSS.escape over any interpolated id before building a selector
- Prefer letter-first ids in generated markup
- For numeric ids, target them with [id="123"] attribute syntax instead
When it happens
Trigger: '#123abc {}', '#1st {}', or any '#'-selector whose name starts with a digit or otherwise is not a valid identifier without escaping.
Common situations: IDs generated from database numeric keys ('#4021') rendered into CSS by templates; anchors like '#2023-report' referenced as style selectors; authors assuming HTML's looser id rules apply to CSS ID-selector syntax.
Related errors
- failed to parse `{}` using lexical: {:?}
- Invalid selector
- Expected ident, '*' or '|' delim tokens
- Expected id, class, attribute or pseudo-class selector
- Invalid attribute name
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/5e327a9dc4011a76.
Report an issue: GitHub.