swc-project/swc · error · swc_css_parser::error::Error
Expected 'left', 'right', 'first' or 'blank' ident
Error message
Expected 'left', 'right', 'first' or 'blank' ident
What it means
Thrown while parsing a @page pseudo page selector. The CSS paged-media grammar allows only the four pseudo pages :left, :right, :first and :blank; when the ident after ':' is none of them (or the token is not an ident), ErrorKind::Expected("'left', 'right', 'first' or 'blank' ident") is raised at that token.
Source
Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:2041
I: ParserInput,
{
fn parse(&mut self) -> PResult<PageSelectorPseudo> {
let span = self.input.cur_span();
expect!(self, ":");
let value = match cur!(self) {
Token::Ident { value, .. }
if matches_eq_ignore_ascii_case!(value, "left", "right", "first", "blank") =>
{
let name: Ident = self.parse()?;
name
}
_ => {
let span = self.input.cur_span();
return Err(Error::new(
span,
ErrorKind::Expected("'left', 'right', 'first' or 'blank' ident"),
));
}
};
Ok(PageSelectorPseudo {
span: span!(self, span.lo),
value,
})
}
}
impl<I> Parse<LayerName> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<LayerName> {View on GitHub (pinned to 5176682b65)
Solutions
- Use only @page :left, @page :right, @page :first, @page :blank
- Use named pages for custom page setups: @page narrow { size: A5; } plus 'page: narrow' on elements
- Drop unsupported pseudo pages before feeding print CSS to swc
Example fix
/* before */
@page :center {
margin: 2cm;
}
/* after */
@page {
margin: 2cm;
} Defensive patterns
Strategy: validation
Validate before calling
const PAGE_PSEUDOS: [&str; 4] = ["left", "right", "first", "blank"];
fn page_pseudos_ok(css: &str) -> bool {
for line in css.lines() {
let t = line.trim();
if t.starts_with("@page") {
for part in t[5..].split_whitespace() {
let p = part.trim_matches(|c| c == ',' || c == '{' || c == '}');
if let Some(name) = p.strip_prefix(':') {
if !PAGE_PSEUDOS.iter().any(|k| name.eq_ignore_ascii_case(k)) {
return false;
}
}
}
}
}
true
} Type guard
fn is_page_pseudo_error(e: &swc_css_parser::error::Error) -> bool {
matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "'left', 'right', 'first' or 'blank' ident")
} Try / catch
match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
Ok(sheet) => handle(sheet),
Err(err) if is_page_pseudo_error(&err) => {
let (span, _) = *err.into_inner();
hint_at_span(css, span, "@page accepts only :left, :right, :first, :blank — use named pages for custom setups");
}
Err(err) => return Err(err.into()),
} Prevention
- Restrict print stylesheet generators to the four legal pseudo pages
- Use named pages (@page narrow {}) for anything custom
- Reject free-form pseudo input from users of your generator
- Test print CSS through swc in CI before shipping
When it happens
Trigger: '@page :center { }', '@page :nth(2) { }', '@page :recto { }' — any pseudo not in the allowed set.
Common situations: Authors assuming nth() page selectors or writing custom pseudo names, print-stylesheet generators exposing arbitrary pseudo input, and porting drafts (recto/verso) that engines never shipped in this form.
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/3fde275ef5cfba23.
Report an issue: GitHub.