{"record":{"id":"ff24a58edd4bece7","repo":"denoland/deno","slug":"empty-selector","errorCode":null,"errorMessage":"Empty selector","messagePattern":"Empty selector","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/js/40_lint_selector.js","lineNumber":773,"sourceCode":"  }\n\n  return result;\n}\n\n/**\n * @param {Selector[]} result\n * @param {Selector[]} stack\n */\nfunction popSelector(result, stack) {\n  const sel = /** @type {Selector} */ (stack.pop());\n\n  if (stack.length === 0) {\n    result.push(sel);\n    stack.push([]);\n  } else {\n    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  }","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/js/40_lint_selector.js#L755-L791","documentation":"Thrown by popSelector() in cli/js/40_lint_selector.js when a nested selector list is popped but the enclosing (parent-level) selector it would attach to is empty — meaning some comma-separated segment or pseudo argument contains no actual selector text. It is the parser's guard against empty selector fragments.","triggerScenarios":"Selectors with an empty segment: \":has()\" (empty parens), \"Foo > , Bar\" or \", Foo\" (empty comma segment), \"Foo,, Bar\". Any place where a selector was expected but nothing preceded the comma/closing brace.","commonSituations":"Programmatically joining selector parts where one part is an empty string; leftover double commas after deleting a selector from a list; writing \":not()\" while sketching a rule and forgetting to fill it in.","solutions":["Remove the empty segment: fill in \":has(...)\", delete leading/double/trailing commas","When building selectors dynamically, filter out empty parts before joining with ', '"],"exampleFix":"// before\nconst sel = parts.join(\", \"); // parts = [\"Foo\", \"\", \"Bar\"] → \"Foo, , Bar\"\n\n// after\nconst sel = parts.filter((p) => p.length > 0).join(\", \");","handlingStrategy":"validation","validationCode":"function noEmptySegments(sel) {\n  const inner = sel.slice(sel.indexOf(\"(\") + 1, sel.lastIndexOf(\")\"));\n  if (/\\(\\s*\\)|,\\s*,|^\\s*,|,\\s*$/.test(sel)) {\n    throw new Error(`empty selector segment in '${sel}'`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When generating selectors from arrays, filter(Boolean) before join(\", \")","Never ship \":has()\" / \":not()\" with empty parens — fill them or drop them"],"tags":["lint","selector","esquery","parser","empty-value"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}