{"record":{"id":"00f244856ebdc24f","repo":"microsoft/playwright","slug":"page-has-been-closed","errorCode":null,"errorMessage":"Page has been closed.","messagePattern":"Page has been closed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/browserContext.ts","lineNumber":600,"sourceCode":"      promises.push(this._deleteAllTempDirs());\n      await progress.race(Promise.all(promises));\n\n      // Custom handler should trigger didCloseInternal itself.\n      if (!this._customCloseHandler)\n        this._didCloseInternal();\n    }\n    await this._closePromise;\n  }\n\n  async newPage(progress: Progress, forStorageState?: boolean): Promise<Page> {\n    let page: Page | undefined;\n    try {\n      this._creatingStorageStatePage = !!forStorageState;\n      page = await progress.race(this.doCreateNewPage());\n      const pageOrError = await progress.race(page.waitForInitializedOrError());\n      if (pageOrError instanceof Page) {\n        if (pageOrError.isClosed())\n          throw new Error('Page has been closed.');\n        return pageOrError;\n      }\n      throw pageOrError;\n    } catch (error) {\n      await page?.close(progress, { reason: 'Failed to create page' }).catch(() => {});\n      throw error;\n    } finally {\n      this._creatingStorageStatePage = false;\n    }\n  }\n\n  addVisitedOrigin(origin: string) {\n    this._origins.add(origin);\n  }\n\n  async storageState(progress: Progress, indexedDB = false, credentials = false): Promise<channels.BrowserContextStorageStateResult> {\n    const result: channels.BrowserContextStorageStateResult = {\n      cookies: await this.cookies(progress),","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/browserContext.ts#L582-L618","documentation":"In `newPage`, after creating a page and waiting for it to initialize, if the page is found to be closed (browser/context closed it, or it crashed) the promise rejects with 'Page has been closed.' It's a race between creation and teardown.","triggerScenarios":"`context.newPage()` while the context/browser is being closed, when the new page crashes immediately on creation, or with concurrent close + newPage.","commonSituations":"Calling newPage() in a finally/teardown racing with context.close(); browser crashes; resource exhaustion causing immediate page close; parallel test workers sharing a closing context.","solutions":["Ensure the context/browser isn't being closed concurrently","Check `context.browser()?.isConnected()` before newPage() in flaky envs","Retry newPage() if the error is transient","Serialize teardown before creating new pages"],"exampleFix":"// before\nawait Promise.all([context.close(), context.newPage()]); // race\n\n// after\nawait context.close();\n// create pages only on a live context","handlingStrategy":"retry","validationCode":"if (!context.browser()?.isConnected()) {\n  throw new Error('Browser/context is closing; cannot create a page.');\n}\nconst page = await context.newPage();","typeGuard":null,"tryCatchPattern":"async function newPageRetry(ctx: BrowserContext, retries = 2) {\n  for (let i = 0; i < retries; i++) {\n    try { return await ctx.newPage(); }\n    catch (e) {\n      if (e instanceof Error && /Page has been closed/.test(e.message) && i < retries - 1) continue;\n      throw e;\n    }\n  }\n  throw new Error('unreachable');\n}","preventionTips":["Never run newPage() concurrently with context.close()","Check browser connection in flaky CI before creating pages","Serialize teardown before creating new pages"],"tags":["browser-context","new-page","race","lifecycle"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}