vitest-dev/vitest · error · Error

Page "${sessionId}" not found in ${this.browserName} browser

Error message

Page "${sessionId}" not found in ${this.browserName} browser.

What it means

Thrown by PlaywrightBrowserProvider.getPage(sessionId) when the given sessionId is not present in the provider's pages map. getPage is the single lookup used by getCommandsContext, getCDPSession, and tracing commands to resolve the active Playwright Page for a session.

Source

Thrown at packages/browser-playwright/src/playwright.ts:570

    const contextOptions = this.options.contextOptions ?? {}
    const options = {
      ...contextOptions,
      ignoreHTTPSErrors: true,
    } satisfies BrowserContextOptions
    // A `null` viewport lets the page adopt the real window size, which is only
    // meaningful for a headed UI. In headless mode there is no real window, so it
    // would inherit the host's device scale factor and produce screenshots that
    // differ from non-UI runs on the same machine.
    if (this.project.config.browser.ui && !this.project.config.browser.headless) {
      options.viewport = null
    }
    return options
  }

  public getPage(sessionId: string): Page {
    const page = this.pages.get(sessionId)
    if (!page) {
      throw new Error(`Page "${sessionId}" not found in ${this.browserName} browser.`)
    }
    return page
  }

  public getCommandsContext(sessionId: string): {
    page: Page
    context: BrowserContext
    frame: () => Promise<Frame>
    readonly iframe: FrameLocator
  } {
    const page = this.getPage(sessionId)
    return {
      page,
      context: this.contexts.get(sessionId)!,
      frame(): Promise<Frame> {
        return new Promise<Frame>((resolve, reject) => {
          const frame = page.frame('vitest-iframe')
          if (frame) {

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Use the sessionId returned by openPage/closePage lifecycle; do not invent ids.
  2. Ensure the page is still open before issuing commands (avoid teardown races).
  3. Re-open the page via openPage if it was closed, rather than reusing the old id.
  4. Confirm the provider instance is the same one that created the page.

Example fix

// before
const page = provider.getPage('stale-or-guessed-id') // throws

// after
const sessionId = await provider.openPage(/* id */, url, { parallel: false })
const page = provider.getPage(sessionId)
Defensive patterns

Strategy: validation

Validate before calling

if (!provider.pages.has(sessionId)) {
  throw new Error(`no page for session ${sessionId}; open it first via openPage`)
}
const page = provider.getPage(sessionId)

Type guard

function hasPage(provider: PlaywrightBrowserProvider, id: string): boolean {
  return provider.pages.has(id)
}

Try / catch

try {
  const page = provider.getPage(sessionId)
} catch (err) {
  if (err instanceof Error && /Page .* not found/.test(err.message)) {
    // re-open or skip; do not reuse stale id
  } else throw err
}

Prevention

When it happens

Trigger: Calling getPage/getCommandsContext/getCDPSession with a sessionId that was never opened, was already closed (openBrowserPage deleted it), or belongs to a different provider instance. Also after the provider is closed and pages.clear() ran.

Common situations: Reusing a stale sessionId after a page close, cross-provider session id collisions, calling commands after teardown, or a race where the page is closed between open and command dispatch.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/3c3bf02a3a19edc9.json. Report an issue: GitHub.