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

Expected Extension name should start with '--'

Error message

Expected Extension name should start with '--'

What it means

The CSS specification reserves identifiers beginning with two dashes (U+002D) for author-defined extensions; <extension-name> is defined to be exactly such an identifier ('--foo', even '--' or '------'). The parser consumed an identifier token, but it does not start with '--', so it cannot serve as an extension name in @custom-media (and similar extension grammars).

Source

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

{
    fn parse(&mut self) -> PResult<ExtensionName> {
        let span = self.input.cur_span();

        if !is!(self, Ident) {
            return Err(Error::new(span, ErrorKind::Expected("indent token")));
        }

        // All extensions defined in this specification use a common syntax for defining
        // their ”names”: the <extension-name> production. An <extension-name> is any
        // identifier that starts with two dashes (U+002D HYPHEN-MINUS), like --foo, or
        // even exotic names like -- or ------. The CSS language will never use
        // identifiers of this form for any language-defined purpose, so it’s safe to
        // use them for author-defined purposes without ever having to worry about
        // colliding with CSS-defined names.
        match bump!(self) {
            Token::Ident { value, raw, .. } => {
                if !value.starts_with("--") {
                    return Err(Error::new(
                        span,
                        ErrorKind::Expected("Extension name should start with '--'"),
                    ));
                }

                Ok(ExtensionName {
                    span,
                    value,
                    raw: Some(raw),
                })
            }
            _ => {
                unreachable!()
            }
        }
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Prefix the name with '--': '@custom-media --wide (min-width: 100px);'
  2. Use exactly two leading dashes — a single dash ('-wide') still fails
  3. Lint custom media names with /^--/ before parsing

Example fix

/* before */
@custom-media wide (min-width: 100px);
/* after */
@custom-media --wide (min-width: 100px);
Defensive patterns

Strategy: type-guard

Validate before calling

function hasDoubleDashPrefix(name) { return name.startsWith('--'); }

Type guard

// Rust
fn is_valid_extension_name(s: &str) -> bool { s.starts_with("--") }

Try / catch

// Rust: normalize before parse instead of catching after
let name = if !is_valid_extension_name(&name) { format!("--{name}") } else { name };

Prevention

When it happens

Trigger: '@custom-media wide (min-width: 100px);' — a plain identifier without the double-dash prefix; also names like '-wide' (single dash) or '_wide'.

Common situations: Authors treating @custom-media like Sass variables and omitting the dashes; migrating from preprocessor variable naming into native CSS custom media; single dash typed instead of two.

Related errors


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