{"record":{"id":"fcffde37c8fb4a7e","repo":"denoland/deno","slug":"multiple-selectors-not-allowed-here","errorCode":null,"errorMessage":"Multiple selectors not allowed here","messagePattern":"Multiple selectors not allowed here","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/js/40_lint_selector.js","lineNumber":789,"sourceCode":"    const prev = /** @type {Selector} */ (stack.at(-1));\n    if (prev.length === 0) {\n      throw new Error(`Empty selector`);\n    }\n\n    const node = prev.at(-1);\n    if (node === undefined) {\n      throw new Error(`Empty node`);\n    }\n\n    if (node.type === PSEUDO_NTH_CHILD) {\n      node.of = sel;\n    } else if (\n      node.type === PSEUDO_HAS || node.type === PSEUDO_IS ||\n      node.type === PSEUDO_NOT\n    ) {\n      node.selectors.push(sel);\n    } else {\n      throw new Error(`Multiple selectors not allowed here`);\n    }\n  }\n}\n\nconst TRUE_FN = () => {\n  return true;\n};\n\n/**\n * @param {Selector} selector\n * @returns {MatcherFn}\n */\nexport function compileSelector(selector) {\n  /** @type {MatcherFn} */\n  let fn = TRUE_FN;\n\n  for (let i = 0; i < selector.length; i++) {\n    const node = selector[i];","sourceCodeStart":771,"sourceCodeEnd":807,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/js/40_lint_selector.js#L771-L807","documentation":"Thrown by popSelector() in cli/js/40_lint_selector.js when a finished selector group must attach to the last node of the enclosing selector, but that node is not one of the node types that accept selector arguments (:nth-child, :has, :is, :not). It is the parser rejecting a selector list placed after an ordinary node.","triggerScenarios":"Grammar that puts a comma-separated group where only a plain selector chain is legal — e.g. malformed nesting like \"Foo > (Bar, Baz)\" or a selector group landing after an element/attribute/relation node. Bounded constructs like :has()/:is()/:not()/:nth-child() accept the group; anything else throws.","commonSituations":"Over-nesting selectors assuming parenthesized grouping works like CSS; malformed hand-written compound selectors after an edit; selector text that survived a bad copy-paste with stray commas.","solutions":["Use a grouping pseudo for the list: wrap it in :is(...) or :has(...)","Split the visitor key into one key per selector and share the callback via a helper"],"exampleFix":"// before\n\"VariableDeclarator > (ArrayPattern, ObjectPattern)\"(node) {},\n\n// after\n\"VariableDeclarator > :is(ArrayPattern, ObjectPattern)\"(node) {},","handlingStrategy":"validation","validationCode":"function groupingOnlyInPseudos(sel) {\n  // reject bare parenthesized groups and lists attached to plain nodes\n  if (/(?<![a-z-]):?(?:[A-Za-z]+)?\\s*\\([^()]*,/.test(sel) && !/:\\w+\\(/.test(sel)) {\n    throw new Error(`selector list must sit inside :is()/:has()/:not(): '${sel}'`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["There is no bare parenthesized grouping — always group lists with :is(...)","Prefer splitting a compound key into two visitor keys sharing one handler function"],"tags":["lint","selector","esquery","parser","syntax"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}