Playwright Test Retries Not Working: Causes, Configuration, and Fixes

Introduction: What Are Playwright Test Retries?

If a Playwright test fails intermittently, retries can run the test again automatically. This feature is useful for identifying flaky tests, especially in CI/CD environments.

For example, you can configure:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  retries: 2

});

With this configuration, Playwright can retry a failed test up to two additional times.

However, developers sometimes report that playwright test retries not working even though retries is configured.

Usually, the problem is not the retry engine itself. Common causes include:

  • The wrong configuration file is being loaded.
  • The test is actually passing.
  • Retries are configured for the wrong project.
  • A CLI or environment configuration changes behavior.
  • The developer expects repeatEach to behave like retries.
  • The test is being run outside Playwright Test.
  • The failure is happening during setup in a way the developer does not expect.
  • The developer is checking the wrong report or result.

This playwright test retries not working tutorial explains how retry behavior works and how to troubleshoot it.


What Are Retries in Playwright?

Retries tell the Playwright Test Runner to rerun a failed test.

For example:

import { test, expect } from ‘@playwright/test’;

test(‘login test’, async ({ page }) => {

  await page.goto(‘https://example.com’);

  await expect(

    page.getByRole(‘heading’, { name: ‘Example Domain’ })

  ).toBeVisible();

});

With:

retries: 2

Playwright can attempt the failed test again.

Retries are particularly useful for detecting tests that:

  • Fail because of timing
  • Depend on unstable external services
  • Have race conditions
  • Are sensitive to CI resource availability
  • Occasionally encounter transient network problems

But retries should not be used to hide unstable automation.

A test that passes only after several retries still needs investigation.


How Playwright Retry Behavior Works

Suppose you configure:

retries: 2

The conceptual flow is:

Attempt 1

   ↓

FAIL

   ↓

Attempt 2

   ↓

FAIL

   ↓

Attempt 3

   ↓

PASS

The test has ultimately passed, but its retry history indicates instability.

Playwright exposes retry information through testInfo.retry.


Configuring Retries Globally in playwright.config.ts

The simplest configuration is:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  testDir: ‘./tests’,

  retries: 2,

  use: {

    headless: true

  }

});

Then run:

npx playwright test

If a test fails and retry conditions apply, Playwright will retry it according to the configured policy.

Verification

Run a deliberately failing test:

import { test, expect } from ‘@playwright/test’;

test(‘retry demonstration’, async () => {

  expect(false).toBe(true);

});

Then:

npx playwright test

You should see retry attempts in the test output.


Configuring Retries for a Specific Project

Large frameworks often have multiple projects.

For example:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  projects: [

    {

      name: ‘chromium’,

      use: {

        browserName: ‘chromium’

      },

      retries: 2

    },

    {

      name: ‘firefox’,

      use: {

        browserName: ‘firefox’

      },

      retries: 1

    }

  ]

});

This lets you control retry behavior independently.

Important troubleshooting point

If you configure retries on one project but execute another project, you may conclude that Playwright test retries are not working.

Check which project you are actually running.

For example:

npx playwright test –project=chromium


Test-Level Retry Configuration

If you want special behavior for a particular group of tests, use a project or configuration strategy rather than assuming every test-level API works like global configuration.

A common approach is to use separate projects for different reliability policies.

This keeps retry rules explicit and easier to maintain.


Using testInfo.retry

testInfo.retry tells you which retry attempt is currently executing.

Example:

import { test } from ‘@playwright/test’;

test(‘inspect retry attempt’, async ({}, testInfo) => {

  console.log(‘Retry number:’, testInfo.retry);

});

The first attempt reports:

Retry number: 0

A subsequent retry reports:

Retry number: 1

Another retry:

Retry number: 2

This is useful when debugging flaky tests.

For example:

import { test } from ‘@playwright/test’;

test(‘retry debugging’, async ({ page }, testInfo) => {

  console.log(`Running attempt ${testInfo.retry + 1}`);

  await page.goto(‘https://example.com’);

});


Difference Between Retries, repeatEach, and Workers

These concepts are often confused.

FeaturePurpose
retriesReruns failed tests
repeatEachRuns tests multiple times intentionally
workersControls parallel test execution

For example:

export default defineConfig({

  retries: 2,

  repeatEach: 3,

  workers: 4

});

These settings do different jobs.

Retries

Used when a test fails.

Repeat Each

Used when you deliberately want to run a test multiple times.

Workers

Control parallel execution.

Therefore, changing:

workers: 1

does not enable retries.


Why Are Playwright Test Retries Not Working?

1. Wrong Configuration File

Problem: You added:

retries: 2

but nothing changes.

Cause: The command may be loading another configuration file.

Fix:

Explicitly specify the configuration:

npx playwright test –config=playwright.config.ts

Best Practice: Keep one clear primary configuration file unless multiple configurations are intentional.


2. The Test Is Passing

Retries happen after failures.

If:

test(‘stable test’, async () => {

  expect(1).toBe(1);

});

passes on the first attempt, there is nothing to retry.

Do not expect Playwright to rerun passed tests because retries is enabled.

Use repeatEach when repeated execution is the actual requirement.


3. Running the Wrong Project

Problem: Retry configuration exists but does not seem effective.

Cause: The test is running under another project.

Check:

npx playwright test –project=chromium

Then verify the chromium project contains the intended retry configuration.


4. Expecting Retries to Fix Every Failure

Retries are a safety mechanism, not a repair mechanism.

If a test consistently fails:

Attempt 1 → FAIL

Attempt 2 → FAIL

Attempt 3 → FAIL

the test is probably genuinely broken.

If it behaves like:

Attempt 1 → FAIL

Attempt 2 → PASS

it may be flaky.

That distinction is critical for debugging.


Retries in Local Development vs CI/CD

A common best practice is to use fewer retries locally and more in CI.

For example:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  retries: process.env.CI ? 2 : 0

});

This means:

  • Local execution → no retries
  • CI execution → two retries

Why?

Local retries can hide problems during development.

CI retries can help identify intermittent failures caused by:

  • Network latency
  • Resource contention
  • Browser startup timing
  • External services

But a retry should still generate evidence for investigation.


Debugging Flaky Tests With Traces and Screenshots

Configure traces:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  retries: 2,

  use: {

    trace: ‘on-first-retry’,

    screenshot: ‘only-on-failure’,

    video: ‘retain-on-failure’

  }

});

This is particularly useful because you can investigate the failed attempt rather than only seeing the final result.

You can open a trace with:

npx playwright show-trace trace.zip

Screenshots can reveal:

  • Unexpected popups
  • Missing elements
  • Loading states
  • Authentication failures
  • Layout problems

Videos can reveal:

  • Timing issues
  • Animations
  • Navigation
  • Unexpected redirects

Real-World Playwright Retry Example

Problem → Cause → Configuration/Fix → Verification → Best Practice

Problem

A dashboard test occasionally fails because the API response is slow.

Test

import { test, expect } from ‘@playwright/test’;

test(‘dashboard loads’, async ({ page }, testInfo) => {

  console.log(`Attempt: ${testInfo.retry + 1}`);

  await page.goto(‘https://example.com/dashboard’);

  await expect(

    page.getByTestId(‘dashboard’)

  ).toBeVisible();

});

Configuration

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  retries: 2,

  use: {

    trace: ‘on-first-retry’,

    screenshot: ‘only-on-failure’

  }

});

Verification

If the output indicates:

Attempt 1 → FAIL

Attempt 2 → PASS

you have evidence of intermittent behavior.

Best Practice

Investigate why the API occasionally responds slowly instead of permanently relying on retries.


Handling Retries With Parallel Execution

Parallel execution can expose resource-related flakiness.

For example:

npx playwright test –workers=8

may behave differently from:

npx playwright test –workers=1

If failures disappear with one worker, investigate:

  • CPU usage
  • Memory
  • Database contention
  • Shared test data
  • API rate limits
  • Port conflicts
  • Shared files

Retries may make the symptoms less visible without fixing the underlying parallelization problem.


Common Configuration Mistakes and Solutions

ProblemCauseSolution
Retries never runTest passesTest failure is required
Wrong retry countWrong configVerify loaded configuration
Retry works locally but not CIDifferent configCheck CI command/environment
Project retry ignoredWrong projectRun intended project
Passed tests don’t repeatMisunderstanding retriesUse repeatEach
Flaky test remainsUnderlying instabilityFix synchronization
Retry hides failureToo many retriesKeep retry count reasonable
No debugging evidenceMissing artifactsEnable trace/screenshots/video

Playwright Retry Best Practices

Follow these guidelines:

  • Keep retries low.
  • Use retries mainly for CI resilience.
  • Do not use retries to hide flaky tests.
  • Investigate tests that pass only after retry.
  • Use testInfo.retry for diagnostics.
  • Capture traces on retry.
  • Capture screenshots for failures.
  • Use HTML reports to identify flaky tests.
  • Keep test data isolated.
  • Avoid shared state between tests.
  • Make API and UI synchronization deterministic.
  • Check worker/resource interactions.
  • Keep CI configuration explicit.

A strong Playwright framework treats retries as a signal about reliability, not as a substitute for stable automation.


Playwright Test Retries Interview Questions With Answers

How do you enable retries in Playwright?

Configure the retries property:

export default defineConfig({

  retries: 2

});

Why are Playwright retries not working?

Check whether the correct configuration file and project are being used, whether the test actually fails, and whether CLI/CI configuration changes the expected behavior.

What does testInfo.retry do?

It identifies the current retry number. The first attempt is 0, the first retry is 1, and so on.

What is the difference between retries and repeatEach?

Retries rerun failed tests. repeatEach intentionally runs a test multiple times regardless of whether previous executions passed.

Should retries be used to fix flaky tests?

No. They can provide temporary resilience and diagnostic evidence, but the underlying flakiness should still be fixed.

Why use retries in CI?

CI environments can expose intermittent timing, network, and resource issues. A small retry count can reduce false-negative pipeline failures while the underlying cause is investigated.


FAQs

How do I enable retries in Playwright?

Add a retries setting to playwright.config.ts:

export default defineConfig({

  retries: 2

});

Then run your tests normally with npx playwright test.

Why are Playwright test retries not working?

Verify the correct configuration file, project, CI environment, and test command. Also remember that retries only occur after a test failure.

Does Playwright retry passed tests?

No. Retries are for failed tests. Use repeatEach when you intentionally want repeated execution.

How many retries should Playwright tests use?

A small number such as one or two is generally more useful than a large retry count. Excessive retries can make CI slower and hide genuine problems.

How can I debug a Playwright test after retry?

Use testInfo.retry, traces, screenshots, videos, and HTML reports to compare the original failure with the retry attempt.

Do Playwright retries work with parallel execution?

Yes. Retries can occur in a parallel test environment, but shared resources and test-data conflicts can cause additional instability.

Leave a Comment

Your email address will not be published. Required fields are marked *