denoland/deno · error · Error
Expected token ' ', but got ' '.\n\n \n ^
Error message
Expected token '${token}', but got '${this.token}'.\n\n${this.input}\n${" ".repeat(this.i)}^ What it means
The selector parser's expect() throws when the token stream does not match the grammar — for example a missing word after ':' or '.', or an empty :nth-child() argument (cli/js/40_lint_selector.js). The message includes the expected and actual token values, which are numeric internal Token enum codes rather than readable names, plus the full selector text and a caret (^) marking the lexer's position in it — use the caret to locate the syntax error.
Solutions
- Look at the caret line in the message — it points at the exact character where parsing failed; fix the key there.
- Remove empty pseudo arguments (":nth-child()" → ":nth-child(1)") and dangling '.' or ':' tokens.
- Simplify the key to a plain node type ("VariableDeclaration") and re-add parts one at a time until the broken fragment is isolated.
- Add a plugin unit test that exercises every visitor key so syntax errors surface in CI.
Example fix
// before
"Expression."(node) { /* ... */ },
":nth-child()"(node) { /* ... */ },
// after
"Expression"(node) { /* ... */ },
":nth-child(1)"(node) { /* ... */ }, Defensive patterns
Strategy: validation
Validate before calling
// Cheap pre-flight for the common malformed-key shapes:
function looksMalformed(key) {
return /[.:]\s*$/.test(key) || /:nth-child\(\s*\)/.test(key) || /\[[^\]]*$/.test(key);
} Prevention
- Never end a selector key with '.' or ':' — a word must follow both.
- Give pseudo functions real arguments (":nth-child()" → ":nth-child(1)").
- The error's caret line marks the exact failing position — read it before changing anything else.
When it happens
Trigger: Visitor keys such as "a." (a word is expected after the dot), ":" alone (a word is expected after the colon), ":nth-child()" (a word is expected but the closing brace comes), or "[attr=" (missing value/closing bracket) — thrown during selector parsing when the rule registers.
Common situations: Typos in hand-written selector keys; trailing separators left after editing; copy-pasting CSS selectors whose grammar differs (empty pseudo arguments); refactoring keys and leaving dangling tokens.
Related errors
- Empty node
- Empty selector
- Expected 'of' keyword in ':nth-child' but got
- Invalid RegExp pattern
- Multiple selector arguments not supported here
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/2920fa88c755a6bb.
Report an issue: GitHub.
Appendix: 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 9ad36f7a2c)