microsoft/playwright · error · InvalidSelectorError

Error while parsing selector

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.

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@de214f440b (2026-08-12). Data as JSON: /api/errors/be2a6baa9abf3b18. Report an issue: GitHub.

Appendix: source

Thrown at packages/isomorphic/selectorParser.ts:362

      } 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 de214f440b)