denoland/deno · error · Error
Unknown pseudo selector: '${lex.value}'
Error message
Unknown pseudo selector: '${lex.value}' What it means
Thrown by the pseudo-selector switch default (cli/js/40_lint_selector.js) when a ':' pseudo-class is encountered that this parser does not implement. It recognizes a fixed set (including :not(), :has(), :is(), :nth-child()); anything else — with or without arguments — hits the default and throws with the offending name.
Source
Thrown at cli/js/40_lint_selector.js:725
stack.push([]);
continue;
}
case "not": {
lex.next();
lex.expect(Token.BraceOpen);
lex.next();
current.push({
type: PSEUDO_NOT,
selectors: [],
});
stack.push([]);
continue;
}
default:
throw new Error(`Unknown pseudo selector: '${lex.value}'`);
}
} else if (lex.token === Token.Comma) {
if (throwOnComma) {
throw new Error(`Multiple selector arguments not supported here`);
}
lex.next();
if (lex.token === Token.Space) {
lex.next();
}
popSelector(result, stack);
stack.push([]);
continue;
} else if (lex.token === Token.BraceClose) {
throwOnComma = false;
popSelector(result, stack);
} else if (lex.token === Token.Op) {View on GitHub (pinned to 89f33cbef2)
Solutions
- Replace the unsupported pseudo with the equivalent supported construct (:matches → :is)
- Express structural conditions inside the visitor callback (track child index yourself) when no pseudo exists
- Check the exact pseudo name for typos against the supported list
Example fix
// before
":matches(CallExpression, NewExpression)"(node) {},
// after
":is(CallExpression, NewExpression)"(node) {}, Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_PSEUDOS = new Set(["has", "is", "not", "nth-child" /* + first/last-child if used */]);
function checkPseudos(sel) {
for (const m of sel.matchAll(/:([a-zA-Z-]+)/g)) {
if (!SUPPORTED_PSEUDOS.has(m[1])) {
throw new Error(`unsupported pseudo ':${m[1]}' in '${sel}'`);
}
}
} Type guard
function usesSupportedPseudos(sel) {
return [...sel.matchAll(/:([a-zA-Z-]+)/g)].every((m) =>
SUPPORTED_PSEUDOS.has(m[1])
);
} Prevention
- Translate from other dialects explicitly: :matches → :is; positional pseudos → visitor-side index tracking
- Keep a cheat sheet of supported pseudos next to your plugin rules
When it happens
Trigger: Visitor-key selectors using unsupported pseudos: ":matches(X)", ":root", ":first-of-type", ":empty", ":statement" — any ':' word not in the supported set. Note :not() takes brace-enclosed arguments here, and unsupported pseudos throw even if they are valid CSS or esquery.
Common situations: Copying a selector from esquery documentation assuming full parity; using CSS structural pseudos (:first-child variants beyond what's supported) on AST nodes; typos like ':hass(...)' or ':nota(...)' that fall through to the default.
Related errors
- Unknown attribute operator: '${s}'
- Expected token '${token}', but got '${this.token}'.\n\n${thi
- Invalid RegExp pattern: ${raw}
- Expected 'of' keyword in ':nth-child' but got: ${lex.value}
- Multiple selector arguments not supported here
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/84b3d3ae46d3f1df.
Report an issue: GitHub.