microsoft/playwright · error · InvalidSelectorError

Error while parsing selector `${selector}`: ${e.message}

Error message

Error while parsing selector `${selector}`: ${e.message}

What it means

Thrown when a regex literal inside an attribute selector (e.g. `[attr=/pattern/flags]`) fails to compile via `new RegExp(source, flags)`. The original RegExp constructor error message is wrapped in an InvalidSelectorError. This indicates the regex body or flags are syntactically invalid JavaScript regex.

Source

Thrown at packages/isomorphic/selectorParser.ts:358

      } else if (inClass && next() === ']') {
        inClass = false;
      } else if (!inClass && next() === '[') {
        inClass = true;
      } else if (!inClass && next() === '/') {
        break;
      }
      source += eat1();
    }
    if (eat1() !== '/')
      syntaxError('parsing regular expression');
    let flags = '';
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
    while (!EOL && next().match(/[dgimsuvy]/))
      flags += eat1();
    try {
      return new RegExp(source, flags);
    } catch (e) {
      throw new InvalidSelectorError(`Error while parsing selector \`${selector}\`: ${e.message}`);
    }
  }

  function readAttributeToken() {
    let token = '';
    skipSpaces();
    if (next() === `'` || next() === `"`)
      token = readQuotedString(next()).slice(1, -1);
    else
      token = readIdentifier();
    if (!token)
      syntaxError('parsing property path');
    return token;
  }

  function readOperator(): AttributeSelectorOperator {
    skipSpaces();
    let op = '';

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Copy the regex body out of the selector and test it in a JS REPL with `new RegExp(body, flags)` to reproduce the underlying SyntaxError.
  2. Fix the regex syntax (balance parens, remove invalid flags, valid quantifier ranges).
  3. Escape any literal '/' inside the pattern or use a character class.
  4. Restrict flags to the allowed set [dgimsuvy].

Example fix

// before
page.locator('text=/(foo/g');  // unbalanced group + flag issues

// after
page.locator('text=/\(foo\)/');
Defensive patterns

Strategy: validation

Validate before calling

function validateRegexAttr(sel: string) {
  const m = sel.match(/=\/(.+)\/([dgimsuvy]*)/);
  if (m) {
    try { new RegExp(m[1], m[2]); }
    catch (e) { throw new Error(`Embedded regex invalid: ${m[1]} / flags ${m[2]}: ${e.message}`); }
  }
}
validateRegexAttr(selector);

Type guard

function isCompilableRegex(source: string, flags: string): boolean {
  try { new RegExp(source, flags); return true; } catch { return false; }
}

Try / catch

try {
  await page.locator(sel).click();
} catch (e) {
  if (/Error while parsing selector/.test(e.message) && e.message.includes('/')) {
    reportInvalidEmbeddedRegex(sel);
  }
  throw e;
}

Prevention

When it happens

Trigger: Using a regex attribute value with an invalid pattern or unsupported flag: `page.locator('text=/.for(/')` (unbalanced paren), `[class=/foo/z/]` (bad flag 'z'), or `[href=/a{2,1/]` (invalid quantifier range). Any `[attr=/.../flags]` where the JS RegExp constructor rejects the source/flags.

Common situations: Porting a regex from another engine (lookbehind, recursion, PCRE-only syntax); typos in flags; unescaped delimiters that terminate the regex early leaving invalid flags; regex copied from a comment without the surrounding slashes.

Related errors


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