denoland/deno · error · Error

Multiple selectors not allowed here

Error message

Multiple selectors not allowed here

What it means

When popSelector (cli/js/40_lint_selector.js) finishes a selector group, the parent node it attaches to must be one that accepts selector arguments: :nth-child (its `of` clause), :has(), :is() or :not(). If the parent's last node is any other node type, `Multiple selectors not allowed here` is thrown — the parser refuses to attach a second selector to a node that takes exactly one. In practice this is an invariant guard; the reachable ways to finish a group all close one of the supported pseudo forms.

Solutions

  1. Simplify the key: ensure every selector list is explicitly wrapped in :is()/:has()/:not(), e.g. "A B:has(C), A B:has(D)" instead of implicit groupings.
  2. Split the rule into multiple visitor keys, each with one plain compound selector.
  3. If the key appears valid, minimize it and report it to the Deno repository as a parser edge case.
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Malformed or degenerate selector keys where a selector group closes against a plain node or combinator instead of a :has()/:is()/:not()/:nth-child node — typically after unusual nesting, stray closing parentheses, or :nth-child forms that desynchronize the parser's group stack.

Common situations: Experimental selector syntax; keys built by string concatenation; unlikely with hand-written well-formed keys.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/fcffde37c8fb4a7e. Report an issue: GitHub.

Appendix: source

Thrown at cli/js/40_lint_selector.js:789

    const prev = /** @type {Selector} */ (stack.at(-1));
    if (prev.length === 0) {
      throw new Error(`Empty selector`);
    }

    const node = prev.at(-1);
    if (node === undefined) {
      throw new Error(`Empty node`);
    }

    if (node.type === PSEUDO_NTH_CHILD) {
      node.of = sel;
    } else if (
      node.type === PSEUDO_HAS || node.type === PSEUDO_IS ||
      node.type === PSEUDO_NOT
    ) {
      node.selectors.push(sel);
    } else {
      throw new Error(`Multiple selectors not allowed here`);
    }
  }
}

const TRUE_FN = () => {
  return true;
};

/**
 * @param {Selector} selector
 * @returns {MatcherFn}
 */
export function compileSelector(selector) {
  /** @type {MatcherFn} */
  let fn = TRUE_FN;

  for (let i = 0; i < selector.length; i++) {
    const node = selector[i];

View on GitHub (pinned to 9ad36f7a2c)