microsoft/playwright · error · Error

Page has been closed.

Error message

Page has been closed.

What it means

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.

Source

Thrown at packages/playwright-core/src/server/browserContext.ts:600

      promises.push(this._deleteAllTempDirs());
      await progress.race(Promise.all(promises));

      // Custom handler should trigger didCloseInternal itself.
      if (!this._customCloseHandler)
        this._didCloseInternal();
    }
    await this._closePromise;
  }

  async newPage(progress: Progress, forStorageState?: boolean): Promise<Page> {
    let page: Page | undefined;
    try {
      this._creatingStorageStatePage = !!forStorageState;
      page = await progress.race(this.doCreateNewPage());
      const pageOrError = await progress.race(page.waitForInitializedOrError());
      if (pageOrError instanceof Page) {
        if (pageOrError.isClosed())
          throw new Error('Page has been closed.');
        return pageOrError;
      }
      throw pageOrError;
    } catch (error) {
      await page?.close(progress, { reason: 'Failed to create page' }).catch(() => {});
      throw error;
    } finally {
      this._creatingStorageStatePage = false;
    }
  }

  addVisitedOrigin(origin: string) {
    this._origins.add(origin);
  }

  async storageState(progress: Progress, indexedDB = false, credentials = false): Promise<channels.BrowserContextStorageStateResult> {
    const result: channels.BrowserContextStorageStateResult = {
      cookies: await this.cookies(progress),

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Ensure the context/browser isn't being closed concurrently
  2. Check `context.browser()?.isConnected()` before newPage() in flaky envs
  3. Retry newPage() if the error is transient
  4. Serialize teardown before creating new pages

Example fix

// before
await Promise.all([context.close(), context.newPage()]); // race

// after
await context.close();
// create pages only on a live context
Defensive patterns

Strategy: retry

Validate before calling

if (!context.browser()?.isConnected()) {
  throw new Error('Browser/context is closing; cannot create a page.');
}
const page = await context.newPage();

Try / catch

async function newPageRetry(ctx: BrowserContext, retries = 2) {
  for (let i = 0; i < retries; i++) {
    try { return await ctx.newPage(); }
    catch (e) {
      if (e instanceof Error && /Page has been closed/.test(e.message) && i < retries - 1) continue;
      throw e;
    }
  }
  throw new Error('unreachable');
}

Prevention

When it happens

Trigger: `context.newPage()` while the context/browser is being closed, when the new page crashes immediately on creation, or with concurrent close + newPage.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/00f244856ebdc24f. Report an issue: GitHub.