Reconstructing every failure from the timeline to the network log
Playwright records a complete trace of screenshots, DOM snapshots, network requests and console output for every failed test run. The Trace Viewer makes this recording searchable and shows exactly which click, which request, or which state caused a test to fail. That replaces hours of guesswork on flaky tests with targeted troubleshooting.
Table of Contents
- 1. Why the Trace Viewer explains flaky tests better than console.log
- 2. Enabling trace recording: configuring trace: 'on-first-retry'
- 3. Anatomy of the Trace Viewer interface: timeline, snapshots, network, console
- 4. Opening traces locally with npx playwright show-trace
- 5. Downloading and inspecting CI trace artifacts
- 6. --debug and the Playwright Inspector
- 7. --ui mode for interactive local debugging
- 8. Correctly categorizing flaky vs. deterministic failures
- 9. Trace Viewer versus classic debugging methods
- 10. Summary
- 11. FAQ
1. Why the Trace Viewer explains flaky tests better than console.log
A failed E2E test in CI is one of the most frustrating situations in everyday development work: the test passes locally but fails on the CI runner, and a single console.log or a screenshot at the end of the run barely reveals what actually happened in the seconds before. The Playwright Trace Viewer solves exactly this problem by recording not just the final state but every single step of a test run: every action, every network request, every DOM change and every console output, synchronized in time and searchable.
The key difference from classic debugging with logging statements is that a trace can be analyzed after the fact without having to run the test again. That is decisive especially for flaky tests that only fail under specific timing conditions, because rerunning locally often does not reproduce the problem at all. The trace file from the failed CI run contains the exact state that led to the failure and can be replayed in the Trace Viewer as often as needed, scrubbed forward and backward, and inspected against the DOM at any point in time.
2. Enabling trace recording: configuring trace: 'on-first-retry'
Traces are enabled via the use option in playwright.config.ts. The setting trace: 'on-first-retry' is the most sensible compromise for most projects: a test that succeeds on the first attempt produces no trace, saving disk space and runtime. Only when a test fails and is automatically retried does Playwright record a full trace on the first retry. That means a recording exists for practically every real failure, without green runs producing unnecessary artifacts.
Alternative values include 'on' for uninterrupted recording of every run, which is useful when debugging a single test file but quickly produces large artifact volumes in CI, and 'retain-on-failure', which produces a trace for every run but only keeps it on a final failure. The retries option must be set so that a second attempt actually happens, otherwise on-first-retry never triggers. Two to three retries are common in CI environments, while zero is usually sufficient locally.
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './e2e',
// Retry failed tests in CI so a trace actually gets recorded
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 4 : undefined,
use: {
baseURL: 'https://staging.mironsoft-shop.test',
// Record a trace only on the first retry of a failing test
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
reporter: [['html', { open: 'never' }], ['github']],
});
3. Anatomy of the Trace Viewer interface: timeline, snapshots, network, console
The Trace Viewer interface is split into several areas that together form a complete picture of the test run. At the top sits the timeline: a horizontal bar with one box per action, color-coded by duration and status. Clicking a box jumps to that exact point in time and loads the matching DOM snapshot in the middle pane, which renders the page exactly as it looked in the browser at that moment, including hover states and applied styles.
To the right, the action tree lists each step with its selector, duration and before/after snapshot. Below that sit tabs for network, listing every HTTP request with status code, headers, payload and timing; console, showing all browser logs and JavaScript errors; and a source tab that displays the test file with the exact executed line highlighted. For assertions there is also a call tab that shows the expected and actual value of a failed expect() side by side, which substantially speeds up debugging value mismatches.
4. Opening traces locally with npx playwright show-trace
After a local test run with trace recording enabled, npx playwright show-trace opens the recording directly in the browser without any separate installation. The command starts a local web server, loads the trace file, and automatically opens a new browser window with the full interface. That works with a single .zip file as well as with several traces at once, which then appear as separate tabs in the viewer and can be compared side by side via drag and drop.
Particularly handy for daily use: the HTML report Playwright generates after every run links failed tests directly with a trace button. Clicking it opens the Trace Viewer straight from the report, without having to manually locate the file path. For fast debugging during development, npx playwright test --trace on followed by npx playwright show-report is often enough to fully inspect every failed test with a single click.
# Run tests locally with tracing forced on for every test
npx playwright test --trace on
# Open the trace for a single failed test directly from the test-results folder
npx playwright show-trace test-results/checkout-flow-should-complete/trace.zip
# Compare two trace files side by side (e.g. before/after a fix)
npx playwright show-trace trace-before.zip trace-after.zip
# Open the interactive HTML report, then click "trace" on any failed test
npx playwright show-report
5. Downloading and inspecting CI trace artifacts
In CI it is not enough to generate traces only locally: they must be saved as artifacts before the runner workspace is deleted after the job. In GitHub Actions, actions/upload-artifact handles that, configured with if: failure() so artifacts are only uploaded on actual failures instead of wasting storage on every green run. The test-results/ folder automatically contains all trace, screenshot and video files for the failed tests.
After downloading the artifact archive from the GitHub Actions interface or via gh run download, the contained trace.zip can be opened locally exactly like a self-generated trace with npx playwright show-trace. It is important to fully extract the archive, since individual network resources and screenshots can live as separate files alongside the actual trace file. Anyone who regularly analyzes CI traces is best served by setting up a fixed local directory for downloaded artifacts, so test runs can be compared over time.
# .github/workflows/e2e.yml
name: E2E Tests
on: [pull_request]
jobs:
playwright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
# Only upload traces when the job actually failed
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-traces
path: test-results/
retention-days: 7
6. --debug and the Playwright Inspector
While the Trace Viewer is meant for after-the-fact analysis, the --debug mode is aimed at debugging during test development. The command npx playwright test --debug launches the browser visibly and pauses before every action, while the Playwright Inspector opens as a separate window. There you can step through the test one action at a time, execute each action individually, and see the current line's selector highlighted live in the browser.
The Inspector also comes with a selector picker that automatically generates a robust Playwright selector when you click on an element in the browser, which saves time especially when writing new tests. For targeted debugging of a single test file, --debug combined with a test-name filter is useful, so that not the entire run pauses but only the relevant test. An await page.pause() call placed in the test code additionally halts execution at any arbitrary point, even without setting the flag globally.
# Debug a single test file interactively, browser visible, paused before each step
npx playwright test checkout.spec.ts --debug
# Debug only one test by name (avoids pausing the whole file)
npx playwright test --debug -g "should apply discount code at checkout"
# Inside a test file, pause execution at an arbitrary point without --debug:
# await page.pause();
7. --ui mode for interactive local debugging
The UI mode, launched with npx playwright test --ui, combines a test overview, the Trace Viewer and a watch mode in a single window. On the left appears a searchable list of all tests, which can be run individually or filtered by file, project or tag with a click. After every run, whether passed or failed, the full trace view with timeline, snapshots and network tab is available directly in the same window, without having to open a separate trace file.
The built-in watch mode automatically reruns tests as soon as the corresponding source code or test file is saved, which noticeably speeds up iteration while fixing a bug. UI mode also shows a time-travel slider directly above the browser preview pane, letting you scrub through every step of a test while the DOM state updates live. For day-to-day test development, UI mode in practice replaces both --debug and manually opening trace files.
# Launch the interactive UI mode for the whole test suite
npx playwright test --ui
# Launch UI mode scoped to a single project (e.g. only Chromium)
npx playwright test --ui --project=chromium
# UI mode respects the same filters as a normal run
npx playwright test --ui checkout.spec.ts
8. Correctly categorizing flaky vs. deterministic failures
Not every failed test should be treated the same way, and the Trace Viewer helps distinguish the two categories cleanly. A deterministic failure occurs on every run under the same conditions, for example because a selector no longer exists after a UI change or an assertion genuinely expects the wrong value. Such failures show up in the trace as a clear red step with an unambiguous error message in the call tab, and the fix is usually to adjust the selector or expected value.
A flaky test, on the other hand, only fails under specific timing or ordering conditions, often because an asynchronous operation like an API call or an animation had not finished when the next action ran. In the trace this typically shows up as a network request that only completes in the network tab after the failed step, or as a DOM snapshot showing an element in a transitional state. The fix is almost always an explicit Playwright auto-waiting condition such as await expect(locator).toBeVisible() instead of a fixed waitForTimeout pause, which only masks the problem instead of fixing it.
9. Trace Viewer versus classic debugging methods
The following overview compares classic, often time-consuming debugging approaches with the corresponding Trace Viewer workflows. The difference is rarely about feasibility, but about the time it takes to actually reach the root cause of a failure.
| Task | Without Trace Viewer | With Trace Viewer | Advantage |
|---|---|---|---|
| Finding the root cause | Guess with console.log and rerun | Step through the timeline | Root cause in minutes, not hours |
| Checking UI state | Only one screenshot at failure time | Scrub the DOM snapshot at any point in time | Full DOM and CSS state visible |
| Reproducing a CI failure | Rerun locally repeatedly, often not reproducible | Download and replay the CI trace | Exact CI state, no reproduction needed |
| Analyzing a network failure | Reproduce manually in browser DevTools | Network tab with status, headers, timing | All requests of the test run in one place |
| Understanding an assertion failure | Manually log expected/actual value | Call tab shows the diff automatically | No code change needed to debug |
The common denominator across every row in the table: the Trace Viewer shifts debugging from an iterative guess-and-run cycle to a single, complete recording that can be searched as often as needed without rerunning the test. Especially for CI-specific failures that never occur locally, that is the decisive time advantage over classic debugging.
Mironsoft
E2E test automation, CI/CD integration and Playwright setups for Magento and Hyva shops
Reliable E2E tests instead of flaky CI runs?
We set up Playwright test suites with clean trace configuration, stable selectors and CI integration, and help analyze existing flaky tests so your pipeline delivers trustworthy results again.
Playwright setup
Trace, screenshot and video configuration for meaningful CI artifacts
Flaky test analysis
Identify root causes with the Trace Viewer and replace them with robust waits
CI/CD integration
Wire trace artifacts, reports and notifications into your pipeline
10. Summary
The Playwright Trace Viewer solves the core problem of E2E debugging: failures that only occur once, particularly in CI, can be fully reconstructed without having to rerun the test. trace: 'on-first-retry' in the configuration ensures a recording exists for every real failure, without burdening green runs unnecessarily. The combination of timeline, DOM snapshots, network tab and console covers practically every root cause, from wrong selectors to timing problems to failed API calls.
For day-to-day test development, --debug with the Playwright Inspector and --ui mode with its integrated watch mode complement each other well: while developing a new test, interactive step-by-step execution helps; after a CI failure, the downloaded trace file delivers the exact root cause. Anyone who uses these tools consistently replaces guesswork on flaky tests with a reproducible, documented debugging workflow.
Playwright Trace Viewer: The Essentials at a Glance
Trace recording
trace: 'on-first-retry' in playwright.config.ts, combined with retries in CI, for complete failure artifacts.
Trace Viewer interface
Timeline, DOM snapshots, network tab and console show every step of a test run synchronized in time.
Local & CI
npx playwright show-trace opens both locally generated and CI-downloaded traces identically.
Interactive debugging
--debug with the Playwright Inspector for single steps, --ui for watch mode and an integrated Trace Viewer.