Skip to content
Playwright · error message

Playwright: expect(locator).toBeVisible() failed

RetryablePlaywright Test runner

Last verified

The exact message
Error: expect(locator).toBeVisible() failed Locator: getByText('Welcome back') Expected: visible Timeout: 5000ms Error: element(s) not found Call log: - Expect "toBeVisible" getByText('Welcome back') with timeout 5000ms - waiting for getByText('Welcome back')

What it means

A web-first assertion in Playwright Test retried for its whole timeout and the condition never became true. Assertions have their own timeout, 5 seconds by default, separate from the 30-second test timeout. The block below the headline tells you what was checked: the locator, what was expected, how long it waited, and, if nothing matched, element(s) not found.

Older Playwright versions printed this as Timed out 5000ms waiting for expect(locator).toBeVisible(); current versions use the ... failed format shown here, so you may see either in search results.

What is not wrong: the assertion mechanism. If element(s) not found appears, the locator matched nothing. If it shows a received value such as hidden, the element exists but is not visible. The fix differs for each.

What it looks like

import { test, expect } from '@playwright/test';

test('login', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('[email protected]');
  await page.getByLabel('Password').fill(process.env.PASSWORD!);
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page).toHaveURL(/dashboard/);
  await expect(page.getByRole('heading', { name: 'Welcome back' }))
    .toBeVisible({ timeout: 15_000 });
});

Why it happens

  • The locator does not match the rendered text or role (exact casing, extra whitespace, a different heading level).
  • The previous step did not actually succeed, for example a login that silently failed.
  • The UI takes longer than 5 seconds after a slow API call.
  • The element is rendered hidden, inside a closed accordion or behind a tab.

How to fix it

  1. Check the Error line: element(s) not found points to the locator; a received state points to visibility.
  2. Open the trace or HTML report screenshot and confirm what the page showed at that moment.
  3. Fix the locator with getByRole or the Pick Locator tool rather than tweaking strings by hand.
  4. Assert the preceding step too (for example the URL after login) so failures surface where they start.
  5. For slow screens, raise just that assertion: expect(locator).toBeVisible({ timeout: 15000 }), or set expect.timeout in config.

How to stop it recurring

Use web-first assertions (expect(locator)...) instead of reading values and comparing them yourself; they retry and produce these detailed messages. Assert intermediate states so a failure points at the step that broke. Configure expect.timeout once for your app's realistic latency instead of sprinkling ad-hoc waits.

Official documentation: playwright.dev/docs/test-assertions. See all Playwright error messages.

Related errors

Definitions

Quick answers

What does "expect(locator).toBeVisible() failed" mean in Playwright?

A web-first assertion in Playwright Test retried for its whole timeout and the condition never became true. Assertions have their own timeout, 5 seconds by default, separate from the 30-second test timeout. The block below the headline tells you what was checked: the locator, what was expected, how long it waited, and, if nothing matched, element(s) not found .

How do I fix "expect(locator).toBeVisible() failed"?

1. Check the Error line: element(s) not found points to the locator; a received state points to visibility. 2. Open the trace or HTML report screenshot and confirm what the page showed at that moment. 3. Fix the locator with getByRole or the Pick Locator tool rather than tweaking strings by hand. 4. Assert the preceding step too (for example the URL after login) so failures surface where they start. 5. For slow screens, raise just that assertion: expect(locator).toBeVisible({ timeout: 15000 }), or set expect.timeout in config.

Run browser automation you can watch and take over

Autonoly runs each job in a real cloud Chromium browser driven by Playwright. Timeouts and detached elements still happen; the difference is that you can watch the run live, see the step that failed, and take control of the browser to finish it.

Also see Live browser control.