{"record":{"id":"2920fa88c755a6bb","repo":"denoland/deno","slug":"expected-token-token-but-got-this-token","errorCode":null,"errorMessage":"Expected token '${token}', but got '${this.token}'.\\n\\n${this.input}\\n${\" \".repeat(this.i)}^","messagePattern":"Expected token '(.+?)', but got '(.+?)'\\.\\\\n\\\\n(.+?)\\\\n(.+?)\\^","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/js/40_lint_selector.js","lineNumber":140,"sourceCode":"  i = -1;\n\n  value = \"\";\n\n  /**\n   * @param {string} input\n   */\n  constructor(input) {\n    this.input = input;\n    this.step();\n    this.next();\n  }\n\n  /**\n   * @param {number} token\n   */\n  expect(token) {\n    if (this.token !== token) {\n      throw new Error(\n        `Expected token '${token}', but got '${this.token}'.\\n\\n${this.input}\\n${\n          \" \".repeat(this.i)\n        }^`,\n      );\n    }\n  }\n\n  /**\n   * @param {number} token\n   */\n  readAsWordUntil(token) {\n    const s = this.i;\n    while (this.token !== Token.EOF && this.token !== token) {\n      this.next();\n    }\n\n    this.start = s;\n    this.end = this.i - 1;","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/js/40_lint_selector.js#L122-L158","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n\"Expression.\"(node) { /* ... */ },\n\":nth-child()\"(node) { /* ... */ },\n\n// after\n\"Expression\"(node) { /* ... */ },\n\":nth-child(1)\"(node) { /* ... */ },","handlingStrategy":"validation","validationCode":"// Cheap pre-flight for the common malformed-key shapes:\nfunction looksMalformed(key) {\n  return /[.:]\\s*$/.test(key) || /:nth-child\\(\\s*\\)/.test(key) || /\\[[^\\]]*$/.test(key);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["deno","deno-lint","lint-plugin","selector","parse-error","syntax"],"backgroundTag":"invalid-selector-syntax","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}