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

Expected {}

Error message

Expected {}

What it means

The expect!() macro is the parser's generic token assertion: it tries to eat a specific token (')', '}', ident, string, ...) and, when the current token is not it, returns ExpectedButGot with the expected token name. The '{}' in the message is filled with the token that was expected at that call site, so this one error kind covers every 'expected X here' site in the CSS parser — the expected-token text and span tell you which grammar position failed.

Source

Thrown at crates/swc_css_parser/src/parser/macros.rs:161

    };
}

macro_rules! eat {
    ($parser:expr, $tt:tt) => {
        if is!($parser, $tt) {
            bump!($parser);
            true
        } else {
            false
        }
    };
}

macro_rules! expect {
    ($parser:expr, $tt:tt) => {
        if !eat!($parser, $tt) {
            let span = $parser.input.cur_span();
            return Err(crate::error::Error::new(
                span,
                crate::error::ErrorKind::ExpectedButGot(stringify!($tt)),
            ));
        }
    };
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Read the expected-token text in the message and the error span, then insert that token at the span location
  2. Balance delimiters around the reported position (the missing token is usually a ')' or '}' belonging to an earlier line)
  3. Run the input through a formatter/linter (prettier, stylelint) to localize the imbalance
  4. If generating CSS, emit open/close pairs from one code path

Example fix

/* before */
@media (min-width: 100px { .a { color: red; } }
/* after */
@media (min-width: 100px) { .a { color: red; } }
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap delimiter-balance check catches the common missing ')'/'}' cases
if (!isBalanced(css)) throw new SyntaxError('unbalanced braces or parens');

Try / catch

// JS: extract the expected token from the message for actionable diagnostics
try { parse(css, opts); } catch (e) {
  const m = e.message.match(/Expected (\S+), but got/);
  if (m) report(`insert '${m[1]}' near offset ${e.span?.start}`); else throw e;
}

Prevention

When it happens

Trigger: Missing ')' closing a media feature: '@media (width: 10px {', missing '}' closing a block, missing '(' after an at-rule keyword, or a missing ident/string where a value is required — any site using expect!(self, ...) whose token does not match.

Common situations: Hand-edited stylesheets with a dropped delimiter; minified CSS where a brace was stripped; templating that conditionally emits an opening construct but not its closer. Because the message names the expected token, developers often misread it as a library bug when it is input syntax.

Related errors


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