swc-project/swc · error · swc_css_parser::error::Error

Expected ident

Error message

Expected ident

What it means

Thrown while parsing a <container-name> — the name slot of @container preludes (and the container-name property path). The token must be a <custom-ident>; anything else (number, string, hash, dimension, or EOF) raises ErrorKind::Expected("ident") at the current token span. CSS-wide keywords are additionally rejected later by the CustomIdent rules with a dedicated error.

Source

Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:2117

        })
    }
}

impl<I> Parse<ContainerName> for Parser<I>
where
    I: ParserInput,
{
    fn parse(&mut self) -> PResult<ContainerName> {
        match cur!(self) {
            tok!("ident") => {
                let custom_ident: CustomIdent = self.parse()?;

                Ok(ContainerName::CustomIdent(custom_ident))
            }
            _ => {
                let span = self.input.cur_span();

                Err(Error::new(span, ErrorKind::Expected("ident")))
            }
        }
    }
}

impl<I> Parse<ContainerQuery> for Parser<I>
where
    I: ParserInput,
{
    fn parse(&mut self) -> PResult<ContainerQuery> {
        let start_pos = self.input.cur_span().lo;
        let mut last_pos;

        let mut queries = Vec::new();

        if is_case_insensitive_ident!(self, "not") {
            let not = self.parse()?;

View on GitHub (pinned to 5176682b65)

Solutions

  1. Give the container an identifier name: @container card (width > 40em) { }
  2. Omit the name for the unnamed query: @container (width > 40em) { }
  3. Set names via the container-name property with a <custom-ident>; avoid css-wide keywords like none/default

Example fix

/* before */
@container "card" (width > 40em) { }

/* after */
@container card (width > 40em) { }
Defensive patterns

Strategy: validation

Validate before calling

fn container_name_ok(name: &str) -> bool {
    let mut chars = name.chars();
    match chars.next() {
        Some(c) if c.is_ascii_alphabetic() || c == '_' || c == '-' => {}
        _ => return false,
    }
    name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
        && !["none", "initial", "inherit", "unset", "revert"].iter().any(|k| name.eq_ignore_ascii_case(k))
}

Type guard

fn is_container_name_error(e: &swc_css_parser::error::Error) -> bool {
    matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "ident")
}

Try / catch

match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
    Ok(sheet) => handle(sheet),
    Err(err) if is_container_name_error(&err) => {
        let (span, _) = *err.into_inner();
        hint_at_span(css, span, "@container expects an <custom-ident> name (or none at all): @container card (width > 40em)");
    }
    Err(err) => return Err(err.into()),
}

Prevention

When it happens

Trigger: '@container 20px (width > 40em)' (dimension as name), '@container "card" (width > 40em)' (string), '@container #main (...)' (hash token).

Common situations: Authors mixing up container-name and container-type values in the shorthand, generated queries where the name variable is empty or numeric, and confusion with the named-page syntax.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/7c74f194226c690f. Report an issue: GitHub.