denoland/deno · error · Error
Unknown attribute operator: '${s}'
Error message
Unknown attribute operator: '${s}' What it means
Thrown by the attribute-operator lookup in the esquery-style selector parser (cli/js/40_lint_selector.js) when a selector uses an operator inside [...] that is not one of the supported ones (=, !=, <, <=, >, >=, ~, +). Lint rule visitor keys are parsed as selectors, so an unsupported operator aborts selector compilation.
Source
Thrown at cli/js/40_lint_selector.js:113
switch (s) {
case "=":
return BinOp.Equal;
case "!=":
return BinOp.NotEqual;
case ">":
return BinOp.Greater;
case ">=":
return BinOp.GreaterThan;
case "<":
return BinOp.Less;
case "<=":
return BinOp.LessThan;
case "~":
return BinOp.Tilde;
case "+":
return BinOp.Plus;
default:
throw new Error(`Unknown attribute operator: '${s}'`);
}
}
export class Lexer {
token = Token.Word;
start = 0;
end = 0;
ch = 0;
i = -1;
value = "";
/**
* @param {string} input
*/
constructor(input) {
this.input = input;
this.step();View on GitHub (pinned to 89f33cbef2)
Solutions
- Replace the unsupported operator with a supported one, or move the matching logic into the visitor callback
- For substring tests, use a regex value with a supported operator, e.g. [name=/foo/] where supported, or filter in code
Example fix
// before
"ObjectExpression[properties.length > 0][key ^= \"data\"]"(node) {},
// after
"ObjectExpression[properties.length > 0]"(node) {
// do the key-prefix test in the visitor body
}, Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_ATTR_OPS = new Set(["=", "!=", "<", "<=", ">", ">=", "~", "+"]);
function checkAttrOps(selector) {
for (const m of selector.matchAll(/\[([^\]]+)\]/g)) {
const op = m[1].match(/(?:!=|=|<=|>=|<|>|~|\+|[^\s=<>~+]+)/)?.[0];
if (op && !SUPPORTED_ATTR_OPS.has(op)) {
throw new Error(`unsupported attribute operator '${op}' in '${selector}'`);
}
}
} Type guard
function usesOnlySupportedAttrOps(selector) {
return ![...selector.matchAll(/[!=<>~^$*]+=/g)].some((m) =>
!["!=", "<=", ">="].includes(m[0])
);
} Prevention
- Restrict attribute selectors to the implemented operator set; push substring/prefix matching into visitor code
- Smoke-test selectors by linting a fixture file in CI whenever you add a new visitor key
When it happens
Trigger: A visitor key / selector like "VariableDeclaration[kind ^= \"const\"]", "[name %= \"x\"]", or "[a $= \"b\"]" — substring/caret/dollar regex-style operators from other selector dialects are not implemented.
Common situations: Copying an attribute selector syntax from CSS attribute selectors or another AST query tool into a Deno lint plugin rule; assuming esquery's full operator set is supported when this parser implements a subset.
Related errors
- Expected token '${token}', but got '${this.token}'.\n\n${thi
- Invalid RegExp pattern: ${raw}
- Expected 'of' keyword in ':nth-child' but got: ${lex.value}
- Unknown pseudo selector: '${lex.value}'
- Multiple selector arguments not supported here
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/2cc75f1e2797ce04.
Report an issue: GitHub.