denoland/deno · error · Error
Expected token '${token}', but got '${this.token}'.\n\n${thi
Error message
Expected token '${token}', but got '${this.token}'.\n\n${this.input}\n${" ".repeat(this.i)}^ What it means
Thrown by Lexer.expect() in cli/js/40_lint_selector.js when the selector grammar requires a specific token but a different one (printed as its numeric token id) is next. The message echoes the full input and a caret pointing at the lexer position, so you can see exactly where parsing derailed.
Source
Thrown at cli/js/40_lint_selector.js:140
i = -1;
value = "";
/**
* @param {string} input
*/
constructor(input) {
this.input = input;
this.step();
this.next();
}
/**
* @param {number} token
*/
expect(token) {
if (this.token !== token) {
throw new Error(
`Expected token '${token}', but got '${this.token}'.\n\n${this.input}\n${
" ".repeat(this.i)
}^`,
);
}
}
/**
* @param {number} token
*/
readAsWordUntil(token) {
const s = this.i;
while (this.token !== Token.EOF && this.token !== token) {
this.next();
}
this.start = s;
this.end = this.i - 1;View on GitHub (pinned to 89f33cbef2)
Solutions
- Read the caret line in the message — it marks the exact character where the expected token was not found
- Balance the selector: every '[' has ']' and every '(' has ')'
- Split overly long selectors into multiple visitor keys or move conditions into the callback
Example fix
// before
"MemberExpression[property.name === \"length\"]"(node) {},
// after
"MemberExpression[property.name=\"length\"]"(node) {}, Defensive patterns
Strategy: try-catch
Validate before calling
// cheap bracket-balance check for hand-built selector strings
function bracketsBalanced(sel) {
const pairs = { "[": "]", "(": ")" };
const stack = [];
for (const ch of sel) {
if (pairs[ch]) stack.push(pairs[ch]);
else if (Object.values(pairs).includes(ch) && stack.pop() !== ch) return false;
}
return stack.length === 0;
} Try / catch
try {
lintFixtureWithPlugin(plugin); // run deno lint on a scratch file
} catch (err) {
if (err instanceof Error && err.message.startsWith("Expected token")) {
// the message contains input + caret; fix the selector at the caret position
console.error(err.message);
}
throw err;
} Prevention
- Keep visitor keys short and literal — avoid concatenating selector fragments
- When composing selectors from parts, validate bracket balance before use
When it happens
Trigger: Malformed visitor-key selectors: unbalanced or missing brackets/parens such as ":has(CallExpression", "ObjectExpression[", "VariableDeclarator > "; missing closing brace in ":nth-child(2"; stray characters where a word or bracket was expected.
Common situations: Hand-writing long compound selectors in a rule's create() return object; a visitor key with a typo after refactoring; dynamically concatenating selector fragments and dropping a closing bracket.
Related errors
- Multiple selectors not allowed here
- Unknown attribute operator: '${s}'
- Invalid RegExp pattern: ${raw}
- Expected 'of' keyword in ':nth-child' but got: ${lex.value}
- Unknown pseudo selector: '${lex.value}'
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/2920fa88c755a6bb.
Report an issue: GitHub.