Playwright · Reliable end-to-end tests

How do you debug a failing Playwright test?

Mediumdebugginginspectortrace viewerUpdated Oct 2026
Quiz this track

Short answer

Run headed with the Inspector, use page.pause() or PWDEBUG=1, read the trace, and enable DEBUG=pw:api for protocol logs. Start from the failing action and its trace snapshot.

Start by reading the failure message: Playwright usually names the locator, the action and the check that failed. Then reproduce with a trace or the Inspector. Guessing at waits without looking at the page state is how a small failure turns into a slow, flaky test.

ts
test("debug checkout", async ({ page }) => {
  await page.goto("/checkout");
  await page.pause();
  await page.getByRole("button", { name: "Pay" }).click();
});
page.pause opens the Inspector and stops execution at that line.

Tools in order of usefulness

  • The HTML report, which shows the failing step and attaches a trace
  • The trace viewer for DOM, network and console state at each step
  • --debug or PWDEBUG=1 to launch the Inspector and step through actions
  • page.pause() for a breakpoint inside one test
  • DEBUG=pw:api for verbose internal API and protocol logs
  • --headed to watch the browser when the issue is visual or timing-related

In the Inspector you can step over actions, resume, and inspect the locator picker. If the element is covered or moving, the trace snapshot often shows why. If the failure is a network response, inspect the request in the trace before changing the test.

Remove page.pause() before running in CI. A paused test waits for a human and will time out, and the pause call has no place in a committed test unless it is behind an explicit debug flag.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What does page.pause do?
  2. 2How do you enable API-level logs?
  3. 3What should you check first in a trace?
  4. 4Why should page.pause not be committed?

Say it in the interview

I start with the report and the failing locator, then open the trace to see the DOM and network at that step. If I need to step through live, I run with the Inspector or add a pause call, and I use the protocol debug logs for details. I try to understand whether the element was missing, covered or slow instead of raising the timeout. And I remove pause calls before committing.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Playwright mock interview and get scored feedback on depth, clarity and confidence.