playwright strict mode violation: selector resolved to multiple elements
Fixes Playwright strict-mode violations by making locators unique. Use when a locator matches 2+ elements. Not for zero-match timeouts.
TL;DR
Strict mode means your locator matched more than one element and Playwright refused to guess. Make the locator unique with a role plus accessible name, scope it to a container, or use nth() as an explicit, documented choice.
Error
Error: strict mode violation: locator('[data-testid="submit"]') resolved to 2 elements:
1) [button data-testid="submit"]Save[/button]
2) [button data-testid="submit"]Save[/button]Steps
- Read the error: it lists the matched elements. Expected: you see why there are two (duplicate component, hidden copy).
- Prefer a role with a name:
page.getByRole('button', { name: 'Save changes' }). Expected: the accessible name disambiguates. - If the page legitimately has two, scope to the container:
page.getByTestId('dialog').getByRole('button', { name: 'Save' }). Expected: one match inside the scope. - If one copy is hidden (mobile/desktop duplicates), filter:
.first()or check which is visible and target it explicitly. Expected: an intentional choice, not an accident. - Only use
.nth(1)when the duplication is stable and documented in a comment. Expected: future readers know the index is deliberate.
When to use
- The error says
strict mode violation. - The page renders the component twice (dialogs, responsive duplicates).
When not to use
- The locator matches zero elements (timeout skill).
- You want to click all matches (use a loop over
.all(), not a single locator).
Tool compatibility
- Playwright 1.30 through latest; strict mode is on by default.
Variant phrasings
locator resolved to N elements
The general form; N tells you how ambiguous the locator is.
getByRole strict mode violation
Even role locators can be ambiguous; add the name or scope.
Why it happens
Playwright's strict mode prevents the classic Selenium bug of acting on the wrong duplicate. It forces you to say which element you mean.
Edge cases
page.locator('...')with CSS is the most common offender; role locators are stricter by construction.- Hidden duplicates from responsive design are a testability smell; consider hiding them with
hiddenattributes. .first()on a list that reorders is flaky; prefer a stable identifier.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_Uu4aVjwhg4Fp7xUDrxozNA