Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use expect.soft() when you want the same test to keep running after an assertion fails. To let later test cases run, keep them out of serial groups, do not use the CLI fail-fast flag -x, and rely on Playwright’s normal worker replacement behavior. Use retries only when you want a failed test attempted again; retries are not a continue-on-error switch.
First decide what “continue” means
Playwright has three different behaviors that are often described as “continue after failure.” They affect different scopes:
| Goal | Use | What happens |
|---|---|---|
| Run more checks in the current test | await expect.soft(...) |
The assertion is recorded as a failure, but the test body continues. |
| Run subsequent test cases | Default test mode, or safe parallel mode | The failed test remains failed. Playwright replaces its worker and can run the next test. |
| Attempt the failed case again | retries or --retries |
The failed test is rerun before the run proceeds. |
These controls are independent. A soft assertion does not retry a matcher, retries do not make unsafe steps run after a failed precondition, and parallelism does not suppress failures.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Continue inside one test with soft assertions
A normal assertion stops the current test at the point of failure. A soft assertion records the failure and allows the next statement to execute. The test still finishes with a failed status, so a defect cannot silently pass.
#1 Best Overall
Basic TypeScript example
import { test, expect } from '@playwright/test';
test('checkout summary', async ({ page }) => {
await page.goto('https://example.com/checkout');
await expect.soft(page.getByTestId('status')).toHaveText('Success');
await expect.soft(page.getByTestId('eta')).toHaveText('1 day');
// This runs even when either assertion above failed.
await page.getByRole('link', { name: 'next page' }).click();
});
Playwright’s web-first matchers, such as toBeVisible() and toHaveText(), already retry while waiting for an asynchronously changing page. Soft mode changes what happens after the matcher has exhausted its normal waiting behavior; it does not add unlimited retries.
Stop before an unsafe action
Continuing is appropriate only when the next operation is independent. If navigation, a button click, or a database mutation requires the earlier check to pass, inspect the accumulated errors and return early:
import { test, expect } from '@playwright/test';
test('submit only when the form is valid', async ({ page }) => {
await page.goto('https://example.com/form');
await expect.soft(page.getByTestId('form-ready')).toHaveText('Ready');
if (test.info().errors.length > 0) {
// The test remains failed, but no dependent action is attempted.
return;
}
await page.getByRole('button', { name: 'Submit' }).click();
});
Use a regular expect when failure must stop the test immediately. Soft assertions are best for collecting several independent diagnostics, such as checking multiple labels, totals, or accessibility markers on the same page.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteLet later tests run after one test fails
In ordinary mode, tests in a file run in order. When a test fails, Playwright shuts down that worker to guarantee a pristine environment, then can run the next test in a replacement worker. This is not the same as aborting the whole run.
Check for serial mode
A serial group has deliberately different semantics. If one test in test.describe.configure({ mode: 'serial' }) fails, the remaining tests in that group are skipped. With retries enabled, Playwright retries the serial group together rather than treating each case as independent.
Rank #2
import { test, expect } from '@playwright/test';
test.describe.configure({ mode: 'serial' });
test('creates an account', async ({ page }) => {
// ...
});
test('edits the account', async ({ page }) => {
// Skipped if the creation test fails.
});
If the tests do not truly depend on one another, remove the serial configuration and give each test its own setup and data. Playwright recommends isolated tests because isolation lets failures be recovered without invalidating unrelated cases.
Check for fail-fast invocation
The CLI option -x stops the run after the first failure. Remove it when you want the rest of the suite to execute:
npx playwright test
Do not confuse workers: 1 with continue-on-failure. That setting limits concurrency; it does not change serial-group rules, retries, or fail-fast behavior.
Choose parallelism deliberately
By default, Playwright runs files in parallel when workers are available, while tests within a file run in order. fullyParallel: true allows tests across files to run in parallel as well. Each parallel test runs in a separate worker, so in-memory variables, shared browser state, and another test’s side effects cannot be reliable dependencies.
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
fullyParallel: true,
workers: 4,
use: {
baseURL: 'https://example.com'
}
});
Use parallel execution when tests are independent and your backend can handle concurrent data creation. Keep dependent workflows in one test or redesign them around isolated fixtures. More workers can reduce wall-clock time, but they can also expose race conditions, exhaust environment capacity, or make shared test data collide.
Retries rerun failures; they do not continue a test body
Set retries when failures are intermittent and you need another attempt. The documented default is zero. A test that fails initially and passes on a retry is reported as flaky, which is useful evidence rather than a clean pass.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsConfigure retries
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
retries: 2
});
Or set them for a run:
npx playwright test --retries=3
After a failure, Playwright starts a new worker and retries the failed test. Once the retry sequence is complete, the runner proceeds according to the test’s mode and any fail-fast setting. Retries increase runtime and can hide a persistent defect if used as a blanket policy, so investigate the underlying cause and choose a count appropriate to your project rather than assuming a universal number.
A practical decision procedure
- Need more assertions in the same test? Replace only independent checks with
expect.soft. - Do later statements require the failed check? Inspect
test.info().errorsand return, or use a normal assertion that stops immediately. - Are later test cases skipped? Look for a serial describe configuration and remove it if the cases can be isolated.
- Does the command stop at the first failure? Remove
-xfrom the invocation. - Is the failure intermittent? Add a measured retry policy and monitor flaky outcomes; do not use retries to make deterministic failures disappear.
- Would concurrency be safe? Enable full parallelism only after eliminating shared mutable state and test-order dependencies.
Troubleshooting common continuation problems
“The next line never runs”
You are probably using a regular assertion, or an earlier action (such as navigation) threw an exception. Convert only the independent assertion to expect.soft. Soft assertions do not catch arbitrary action errors.
“The test is marked passed even though a soft check failed”
That is not expected: a soft assertion records an error and the test should be reported as failed. Verify that you imported expect from @playwright/test, that the assertion is awaited, and that your reporter is not hiding failed results.
“Tests after the failure are skipped”
Check whether they share a serial group. Also inspect hooks: a failing beforeAll or fixture setup can prevent dependent tests from starting. Move setup to isolated fixtures or separate the workflow when independence is intended.
Rank #4
“The entire run stops immediately”
Look for -x in the command, CI wrapper, or package script. Remove it for a full run. A worker restart after failure is normal and should not be mistaken for a whole-run abort.
“Retries make CI much slower”
Every retry is another browser attempt, and serial groups may be rerun together. Start with a low count, collect traces and error output, and fix deterministic failures instead of increasing retries indefinitely.
“Parallel tests fail only when workers increase”
Search for shared accounts, fixed filenames, mutable environment variables, or assumptions about test order. Give each test unique data and cleanup that is safe when tests overlap, or reduce parallelism for the genuinely shared portion.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Capture failure evidence without adding brittle browser steps
When a failed run needs screenshots for CI artifacts, the browser test itself remains the right place for state-specific captures. For independent page snapshots, documentation pages, or post-deployment checks, ScreenshotNeo provides a single HTTP screenshot endpoint and an MCP server for AI agents. It removes known cookie-consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the result identified by response headers.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Or skip the browser setup
Use the ScreenshotNeo API when you need a clean page image without launching Playwright yourself. The API supports PNG, JPEG, WebP, and PDF output, and the options include full-page lazy-image loading, selectors, device presets, dark mode, custom CSS or JavaScript, waits, request blocking, authentication headers, cookies, geolocation, resizing, caching, signed links, asynchronous jobs, bulk capture, and usage reporting. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for parameters. A basic call is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; Growth is $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. Sign up free for ScreenshotNeo.
FAQ
Does a soft assertion make a failed test pass?
No. It lets execution continue, but the recorded assertion error still makes the test fail.
Recommended Free Tools
Should I use retries for every CI failure?
No. Retries are useful for intermittent failures; deterministic failures should be fixed rather than repeatedly rerun.
Can serial tests continue after one fails?
Not within that serial group. Subsequent tests are skipped, so remove serial mode only after making the tests independent.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

