microsoft/playwright · error · Error

Conflicting exactness in internal:role selector: ${stringify

Error message

Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}

What it means

Thrown while converting an internal:role selector into a locator: the role's 'name' attribute and another already-processed attribute disagree on case-sensitivity. In Playwright's serialized form, case-sensitivity encodes exactness (case-sensitive => exact). If 'name' sets exact=true but a previously parsed attribute (e.g. an earlier 'description') set exact=false (or vice versa), the conflict is rejected.

Source

Thrown at packages/isomorphic/locatorGenerators.ts:167

      continue;
    }
    if (part.name === 'internal:chain') {
      const inners = innerAsLocators(factory, (part.body as NestedSelectorBody).parsed, false, maxOutputSize);
      tokens.push(inners.map(inner => factory.generateLocator(base, 'chain', inner)));
      continue;
    }
    if (part.name === 'internal:label') {
      const { exact, text } = detectExact(part.body as string);
      tokens.push([factory.generateLocator(base, 'label', text, { exact })]);
      continue;
    }
    if (part.name === 'internal:role') {
      const attrSelector = parseAttributeSelector(part.body as string, true);
      const options: LocatorOptions = { attrs: [] };
      for (const attr of attrSelector.attributes) {
        if (attr.name === 'name') {
          if (options.exact !== undefined && options.exact !== attr.caseSensitive)
            throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);
          options.exact = attr.caseSensitive;
          options.name = attr.value;
        } else if (attr.name === 'description') {
          if (options.exact !== undefined && options.exact !== attr.caseSensitive)
            throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);
          options.exact = attr.caseSensitive;
          options.description = attr.value;
        } else {
          if (attr.name === 'level' && typeof attr.value === 'string')
            attr.value = +attr.value;
          options.attrs!.push({ name: attr.name === 'include-hidden' ? 'includeHidden' : attr.name, value: attr.value });
        }
      }
      tokens.push([factory.generateLocator(base, 'role', attrSelector.name, options)]);
      continue;
    }
    if (part.name === 'internal:testid') {
      const attrSelector = parseAttributeSelector(part.body as string, true);

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Make name and description matchers agree on case-sensitivity (both exact or both non-exact) in the role locator.
  2. Stop hand-writing internal:role strings — use getByRole(role, { name, exact, description }) so Playwright serializes consistent flags.
  3. Re-generate the locator with codegen and use that output verbatim.

Example fix

// before (inconsistent flags)
internal:role=button[name="Save"s][description="save"] // name exact, description not

// after (consistent)
internal:role=button[name="Save"s][description="save"s]
Defensive patterns

Strategy: validation

Validate before calling

function roleExactnessConsistent(opts: {name?:{exact?:boolean}; description?:{exact?:boolean}}): boolean {
  const e = opts.name?.exact;
  const d = opts.description?.exact;
  return e === undefined || d === undefined || e === d;
}

Try / catch

try { await page.locator(roleSelector).click(); }
catch (e) { if (/Conflicting exactness/.test(e.message)) { /* align flags and retry */ } else throw e; }

Prevention

When it happens

Trigger: A hand-constructed or serialized internal:role selector where name= uses a case-sensitive matcher (e.g. name="X" with the 's' flag) but a prior description= (or repeated name=) used a case-insensitive one, producing contradictory exactness. Equivalent userland: calling getByRole with conflicting exact semantics across name/description.

Common situations: Manually editing serialized locators or round-tripping them; programmatically building internal:role strings; mixing exact and non-exact matchers on the same role locator; bugs in code that generates selector strings from option maps.

Related errors


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