{"record":{"id":"9de994b9b279b166","repo":"microsoft/playwright","slug":"the-page-has-closed","errorCode":null,"errorMessage":"The page has closed","messagePattern":"The page has closed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/page.ts","lineNumber":754,"sourceCode":"      const areEqualScreenshots = (actual: Buffer | undefined, expected: Buffer | undefined, previous: Buffer | undefined) => {\n        const comparatorResult = actual && expected ? comparator(actual, expected, options) : undefined;\n        if (comparatorResult !== undefined && !!comparatorResult === !!options.isNot)\n          return true;\n        if (comparatorResult)\n          intermediateResult = { errorMessage: comparatorResult.errorMessage, diff: comparatorResult.diff, actual, previous };\n        return false;\n      };\n      let actual: Buffer | undefined;\n      let previous: Buffer | undefined;\n      const pollIntervals = [0, 100, 250, 500];\n      if (options.expected)\n        progress.log(`  verifying given screenshot expectation`);\n      else\n        progress.log(`  generating new stable screenshot expectation`);\n      let isFirstIteration = true;\n      while (true) {\n        if (this.isClosed())\n          throw new Error('The page has closed');\n        const screenshotTimeout = pollIntervals.shift() ?? 1000;\n        if (screenshotTimeout)\n          progress.log(`waiting ${screenshotTimeout}ms before taking screenshot`);\n        previous = actual;\n        actual = await rafrafScreenshot(progress, screenshotTimeout).catch(e => {\n          if (this.mainFrame().isNonRetriableError(e))\n            throw e;\n          progress.log(`failed to take screenshot - ` + e.message);\n          return undefined;\n        });\n        if (!actual)\n          continue;\n        // Compare against expectation for the first iteration.\n        const expectation = options.expected && isFirstIteration ? options.expected : previous;\n        if (areEqualScreenshots(actual, expectation, previous))\n          break;\n        if (intermediateResult)\n          progress.log(intermediateResult.errorMessage);","sourceCodeStart":736,"sourceCodeEnd":772,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/page.ts#L736-L772","documentation":"Thrown inside the expectScreenshot polling loop when the Page becomes closed mid-wait. The screenshot matcher retries until the image stabilizes, and each iteration re-checks page liveness; a closed page cannot produce further screenshots, so the loop aborts with this message rather than timing out.","triggerScenarios":"The page (or its browser) is closed, crashes, or navigates to a destroy trigger while expect(page).toHaveScreenshot() is polling; page.close() called from another async branch during the assertion; the web app calls window.close(); the browser process is killed by the OS.","commonSituations":"A test that closes the page in a finally block racing with a still-running screenshot assertion; an app that self-closes (popup, OAuth flow); resource exhaustion or OOM killing the browser during a heavy screenshot comparison.","solutions":["Ensure no concurrent code path closes the page while the screenshot assertion is in flight; await the assertion before calling page.close().","Increase the page/script timeout or reduce page load so the assertion completes before any teardown.","Wrap the assertion and treat a 'page closed' error as a signal to re-create the page, or use a scoped fixture that owns the page lifetime."],"exampleFix":"// before\nconst assert = expect(page).toHaveScreenshot('x.png');\nawait page.close(); // races with the assertion\nawait assert;\n// after\nawait expect(page).toHaveScreenshot('x.png');\nawait page.close();","handlingStrategy":"try-catch","validationCode":"if (page.isClosed()) throw new Error('page already closed; skip screenshot assertion');","typeGuard":null,"tryCatchPattern":"try {\n  await expect(page).toHaveScreenshot('home.png');\n} catch (e) {\n  if (/page has closed/i.test(e.message)) {\n    // page died mid-assertion: recreate or skip rather than retry blindly\n    throw new Error('Screenshot assertion aborted: page closed unexpectedly');\n  }\n  throw e;\n}","preventionTips":["Await screenshot assertions fully before any page/browser teardown.","Avoid closing the page from concurrent async branches.","Watch for app-level self-close (popups, window.close()) and handle them before asserting."],"tags":["screenshot","tohavescreenshot","page-closed","race-condition","lifecycle"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}