microsoft/playwright · error · InvalidSelectorError

Error while parsing selector `${selector}` - selector cannot

Error message

Error while parsing selector `${selector}` - selector cannot be empty

What it means

Thrown by parseAttributeSelector at the end of parsing when the selector has neither a name (engine prefix) nor any attributes. It signals the input reduced to nothing meaningful, e.g. an empty string or whitespace-only input fed to the attribute selector parser.

Source

Thrown at packages/isomorphic/selectorParser.ts:465

    if (operator !== '=' && typeof value !== 'string')
      throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);
    return { name: jsonPath.join('.'), jsonPath, op: operator, value, caseSensitive };
  }

  const result: AttributeSelector = {
    name: '',
    attributes: [],
  };
  result.name = readIdentifier();
  skipSpaces();
  while (next() === '[') {
    result.attributes.push(readAttribute());
    skipSpaces();
  }
  if (!EOL)
    syntaxError(undefined);
  if (!result.name && !result.attributes.length)
    throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`);
  return result;
}

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Guard the caller to reject empty/whitespace selector strings before parsing.
  2. Provide a non-empty default or fail fast with a clearer upstream error.
  3. Trim and validate selector input at the boundary.

Example fix

// before
const name = process.env.LABEL ?? '';
page.locator(`text=${name}`);  // name empty -> selector cannot be empty

// after
const name = (process.env.LABEL ?? '').trim();
if (!name) throw new Error('LABEL env var must be set');
page.locator(`text=${name}`);
Defensive patterns

Strategy: validation

Validate before calling

function requireNonEmptySelector(sel: string) {
  if (typeof sel !== 'string' || sel.trim().length === 0)
    throw new Error('Selector must be a non-empty string');
}
requireNonEmptySelector(selector);

Type guard

function isNonEmptySelector(sel: unknown): sel is string {
  return typeof sel === 'string' && sel.trim().length > 0;
}

Try / catch

try {
  await page.locator(sel).click();
} catch (e) {
  if (/selector cannot be empty/.test(e.message)) {
    throw new Error('Refusing empty selector; check the source of the value');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `parseAttributeSelector('', false)`, `parseAttributeSelector(' ', false)`, or `parseAttributeSelector('[ ]', false)` where readIdentifier yields '' and no attributes are collected. Typically reached via the text/attribute engine with an empty inner expression.

Common situations: Dynamic selector assembly that produces an empty fragment; whitespace-only input from a config value; refactoring that left a placeholder variable empty.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/6e6693d21d90e39b. Report an issue: GitHub.