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
- Make name and description matchers agree on case-sensitivity (both exact or both non-exact) in the role locator.
- Stop hand-writing internal:role strings — use getByRole(role, { name, exact, description }) so Playwright serializes consistent flags.
- 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
- Build role locators via getByRole with a single exact option, not hand-written internal:role strings.
- Keep name and description matchers consistent in case-sensitivity.
- Regenerate locators with codegen rather than editing serialized forms.
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
- Selector "${selector}" does not match any element
- Unsupported token "${unsupportedToken.toSource()}" while par
- Error while parsing css selector "${selector}". Did you mean
- Malformed selector: ${part.name}=${part.body}
- "${parts[0].name}" selector cannot be first
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/ee882a3df687243c.
Report an issue: GitHub.