denoland/deno · error · Error

Empty selector

Error message

Empty selector

What it means

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.

Source

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

  }

  return result;
}

/**
 * @param {Selector[]} result
 * @param {Selector[]} stack
 */
function popSelector(result, stack) {
  const sel = /** @type {Selector} */ (stack.pop());

  if (stack.length === 0) {
    result.push(sel);
    stack.push([]);
  } else {
    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`);
    }
  }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Remove the empty segment: fill in ":has(...)", delete leading/double/trailing commas
  2. When building selectors dynamically, filter out empty parts before joining with ', '

Example fix

// before
const sel = parts.join(", "); // parts = ["Foo", "", "Bar"] → "Foo, , Bar"

// after
const sel = parts.filter((p) => p.length > 0).join(", ");
Defensive patterns

Strategy: validation

Validate before calling

function noEmptySegments(sel) {
  const inner = sel.slice(sel.indexOf("(") + 1, sel.lastIndexOf(")"));
  if (/\(\s*\)|,\s*,|^\s*,|,\s*$/.test(sel)) {
    throw new Error(`empty selector segment in '${sel}'`);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/ff24a58edd4bece7. Report an issue: GitHub.