{"record":{"id":"a3c06eef269ba646","repo":"swc-project/swc","slug":"invalid-attribute-matcher","errorCode":null,"errorMessage":"Invalid attribute matcher","messagePattern":"Invalid attribute matcher","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/swc_css_parser/src/parser/selectors/mod.rs","lineNumber":790,"sourceCode":"            }\n            tok!(\"*\") => {\n                bump!(self);\n                expect!(self, \"=\");\n\n                Ok(AttributeSelectorMatcher {\n                    span: span!(self, span.lo),\n                    value: AttributeSelectorMatcherValue::Asterisk,\n                })\n            }\n            tok!(\"=\") => {\n                bump!(self);\n\n                Ok(AttributeSelectorMatcher {\n                    span: span!(self, span.lo),\n                    value: AttributeSelectorMatcherValue::Equals,\n                })\n            }\n            _ => return Err(Error::new(span, ErrorKind::InvalidAttrSelectorMatcher)),\n        }\n    }\n}\n\nimpl<I> Parse<AttributeSelectorValue> for Parser<I>\nwhere\n    I: ParserInput,\n{\n    fn parse(&mut self) -> PResult<AttributeSelectorValue> {\n        match cur!(self) {\n            tok!(\"ident\") => {\n                let ident = self.parse()?;\n\n                Ok(AttributeSelectorValue::Ident(ident))\n            }\n            tok!(\"string\") => {\n                let string = self.parse()?;\n","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_css_parser/src/parser/selectors/mod.rs#L772-L808","documentation":"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.","triggerScenarios":"'[href!=\"x\"]', '[attr==\"v\"]', '[lang| ]' — any '[name <junk> value]' where the operator token is not one of the six valid matchers.","commonSituations":"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.","solutions":["For negation use :not(): ':not([attr=\"v\"])'","Fix the operator to a valid one: '[attr=\"v\"]', '[attr~=\"v\"]', '[attr^=\"v\"]', '[attr$=\"v\"]', '[attr*=\"v\"]', '[attr|=\"v\"]'","Lint for '!=' and '==' inside brackets"],"exampleFix":"/* before */\n[href!=\"https\"] { color: red; }\n/* after */\n:not([href=\"https\"]) { color: red; }","handlingStrategy":"validation","validationCode":"const VALID_MATCHERS = new Set(['~=', '|=', '^=', '$=', '*=', '=']);\nfunction matcherValid(sel) {\n  const m = sel.match(/\\[\\s*[\\w\\|-]+\\s*([^\\]]*?)\\s*[^\\s\\]]*\\s*[^\\]]*\\]/);\n  const op = sel.match(/([~|^$*]?=)/g) || [];\n  return op.every(o => VALID_MATCHERS.has(o));\n}","typeGuard":null,"tryCatchPattern":"// JS\ntry { parseSelector(sel, opts); } catch (e) { if (/attribute matcher/.test(e.message)) report('CSS has no != operator; use :not([attr=...])'); else throw e; }","preventionTips":["Remember '!=' does not exist in CSS — use :not()","Lint for '!=' and '==' inside attribute selectors","Keep a snippet of the six valid matchers next to selector-building code"],"tags":["css","selector","attribute-selector","operator"],"backgroundTag":"css-attribute-selector-syntax-error","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}