swc-project/swc · error · Error
Unexpected character in hex color
Error message
Unexpected character in hex color
What it means
Thrown by Parse<HexColor> in swc_css_parser when the token is a hash but its value contains characters outside [0-9a-fA-F]. After bumping Token::Hash it validates every char with is_ascii_hexdigit(); idents-as-hashes such as '#gg', '#ff00zz', or '#red' (r is not a hex digit) fail with the span of the whole hash token. Note the parser does not enforce 3/4/6/8 digit lengths here - only the character set.
Source
Thrown at crates/swc_css_parser/src/parser/values_and_units/mod.rs:2434
}
}
}
impl<I> Parse<HexColor> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<HexColor> {
let span = self.input.cur_span();
if !is!(self, "#") {
return Err(Error::new(span, ErrorKind::Expected("hash token")));
}
match bump!(self) {
Token::Hash { value, raw, .. } => {
if value.chars().any(|x| !x.is_ascii_hexdigit()) {
return Err(Error::new(
span,
ErrorKind::Unexpected("character in hex color"),
));
}
Ok(HexColor {
span,
value,
raw: Some(raw),
})
}
_ => {
unreachable!()
}
}
}
}
View on GitHub (pinned to 5176682b65)
Solutions
- Fix the hex digits: '#gg' -> '#ccc'-style valid hex; only 0-9 and a-f characters.
- If the string is an id/anchor ('#main'), it is not a color; move it out of the color grammar.
- Validate hex bodies with ^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$ before parsing.
Example fix
/* before */
a { color: #ff00zz; }
/* after */
a { color: #ff00aa; } Defensive patterns
Strategy: validation
Validate before calling
const HEX = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
function isValidHexColor(v: string): boolean {
return HEX.test(v.trim());
} Type guard
fn is_valid_hex_color(v: &str) -> bool {
let b = v.as_bytes();
matches!(b.len(), 4 | 5 | 7 | 9)
&& b[0] == b'#'
&& b[1..].iter().all(|c| c.is_ascii_hexdigit())
} Try / catch
use swc_css_parser::error::ErrorKind;
if let Err(e) = parse_input::<Stylesheet>(src, opts) {
if matches!(e.kind(), ErrorKind::Unexpected("character in hex color")) {
return Err(format!("bad hex digits at {:?}", e.span()).into());
}
return Err(e.into());
} Prevention
- Validate hex bodies (and ideally 3/4/6/8 lengths) with a regex before parsing.
- Never feed '#id'-style anchors or CSS-module class names into color slots.
- When mutating hex strings (darken/lighten), assert the charset stays [0-9a-f].
When it happens
Trigger: Values like 'color: #gg', 'color: #ff00zz', 'color: #0f0f0g', or CSS-module class selectors mistakenly parsed as colors ('#.side' style content in a color slot).
Common situations: Hash-prefixed identifiers mistaken for colors (e.g. '#main'), color strings with g-z characters from bad copy-paste, and hand-rolled color shorteners corrupting hex digits.
Related errors
- Expected hash token
- Expected left comparison operator should be equal right comp
- percentage, functions (math functions) or ident (with 'none'
- number, functions (math functions) or ident (with 'none' val
- number, function (math functions) or ident (with 'none' valu
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/81b1e1d14a96581e.
Report an issue: GitHub.