vitest-dev/vitest · error · Error
Page " " not found in browser.
Error message
Page "${sessionId}" not found in ${this.browserName} browser. What it means
PlaywrightBrowserProvider.getPage looks up the Page for a session id in an internal Map. If the session id was never opened, was already closed (openBrowserPage closes the prior page), or the provider was reset, the lookup returns undefined and getPage throws. getPage backs getCommandsContext, getCDPSession, and most browser command entry points.
Solutions
- Always obtain the sessionId from the current test context, do not cache it across async boundaries that may recycle the page.
- Avoid manually opening/closing pages; let vitest manage the lifecycle per test.
- If running parallel tests, ensure each test uses its own session and does not reference another's sessionId.
- Check that you are not calling browser commands after the test/session has finished.
Example fix
// before const id = currentSessionId // ... test ends, page recycled ... await provider.getPage(id) // throws // after // always derive session from the active test; never reuse across tests const page = provider.getCommandsContext(activeSessionId).page
Defensive patterns
Strategy: validation
Validate before calling
// always derive the sessionId from the active context; do not cache
function useCurrentPage(provider: { getPage: (id: string) => unknown }, sessionId: string) {
if (!sessionId) throw new Error('sessionId is required')
return provider.getPage(sessionId)
} Type guard
function hasPage(provider: { pages: Map<string, unknown> }, sessionId: string): boolean {
return provider.pages.has(sessionId)
} Try / catch
try {
const page = provider.getPage(sessionId)
} catch (err) {
if (err instanceof Error && err.message.includes('not found')) {
// session was recycled; re-acquire from current test context or skip
return
}
throw err
} Prevention
- Never cache sessionId across tests or async gaps that may recycle the page.
- Let vitest manage page lifecycle; avoid manual open/close.
- For parallel tests, keep each session's id isolated.
When it happens
Trigger: Using a sessionId after the page was closed (e.g., after parallel re-entry which closes the previous page), passing a wrong/stale sessionId to a command, calling browser APIs after the test/session ended, or a race where the page is still being opened.
Common situations: Reusing a captured sessionId across navigations that recycled the page; concurrency/parallel sessions colliding; calling page APIs in afterAll after the session was torn down; typo or mismatched sessionId between caller and provider.
Related errors
- [vitest] The provider was closed.
- Cannot take a screenshot without a test path
- Session " " not found.
- Browser is not initialized
- Browser provider is not defined for the project
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/3c3bf02a3a19edc9.
Report an issue: GitHub.
Appendix: 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 1fa9837ec2)