swc-project/swc · error · Error

Invalid attribute matcher

Error message

Invalid attribute matcher

What it means

The matcher between attribute name and value must be one of the CSS-defined operators: '~=', '|=', '^=', '$=', '*=', or plain '='. After the (optional) value-side parsing reached the matcher position, the token was none of these — commonly '!=', '==', or a bare '~'/'|' without the '=' — so ErrorKind::InvalidAttrSelectorMatcher is thrown.

Source

Thrown at crates/swc_css_parser/src/parser/selectors/mod.rs:790

            }
            tok!("*") => {
                bump!(self);
                expect!(self, "=");

                Ok(AttributeSelectorMatcher {
                    span: span!(self, span.lo),
                    value: AttributeSelectorMatcherValue::Asterisk,
                })
            }
            tok!("=") => {
                bump!(self);

                Ok(AttributeSelectorMatcher {
                    span: span!(self, span.lo),
                    value: AttributeSelectorMatcherValue::Equals,
                })
            }
            _ => return Err(Error::new(span, ErrorKind::InvalidAttrSelectorMatcher)),
        }
    }
}

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

                Ok(AttributeSelectorValue::Ident(ident))
            }
            tok!("string") => {
                let string = self.parse()?;

View on GitHub (pinned to 5176682b65)

Solutions

  1. For negation use :not(): ':not([attr="v"])'
  2. Fix the operator to a valid one: '[attr="v"]', '[attr~="v"]', '[attr^="v"]', '[attr$="v"]', '[attr*="v"]', '[attr|="v"]'
  3. Lint for '!=' and '==' inside brackets

Example fix

/* before */
[href!="https"] { color: red; }
/* after */
:not([href="https"]) { color: red; }
Defensive patterns

Strategy: validation

Validate before calling

const VALID_MATCHERS = new Set(['~=', '|=', '^=', '$=', '*=', '=']);
function matcherValid(sel) {
  const m = sel.match(/\[\s*[\w\|-]+\s*([^\]]*?)\s*[^\s\]]*\s*[^\]]*\]/);
  const op = sel.match(/([~|^$*]?=)/g) || [];
  return op.every(o => VALID_MATCHERS.has(o));
}

Try / catch

// JS
try { parseSelector(sel, opts); } catch (e) { if (/attribute matcher/.test(e.message)) report('CSS has no != operator; use :not([attr=...])'); else throw e; }

Prevention

When it happens

Trigger: '[href!="x"]', '[attr=="v"]', '[lang| ]' — any '[name <junk> value]' where the operator token is not one of the six valid matchers.

Common situations: Developers expecting '!=' (not in CSS syntax — negation uses :not([attr="x"])); muscle memory from attribute selectors in other languages/frameworks (jQuery-style '[attr!=v]'); typo'd '=' doubled by find-replace.

Related errors


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