vitest-dev/vitest · error · Error
[vitest] The provider was closed.
Error message
[vitest] The provider was closed.
What it means
_throwIfClosing is called at multiple checkpoints (createContext, openBrowserPage, openPage) to abort work if the provider has begun closing. When this.closing is true it disposes the in-flight disposable, clears pages/contexts/browser, and throws so callers stop using a half-torn-down provider. close() sets this.closing = true during shutdown.
Solutions
- Increase test timeouts if tests are being killed mid-flight, or shorten the tests so they finish before teardown.
- Avoid starting new browser operations in afterAll/global teardown; the provider may already be closing.
- Handle SIGTERM in your CI gracefully (do not send a second kill -9 immediately).
- If reproducible, file a Vitest issue with the timing — operations should drain before close.
Defensive patterns
Strategy: try-catch
Validate before calling
// you cannot reliably pre-validate a race with close(), but you can avoid it: // do not start browser operations in afterAll/global teardown.
Try / catch
try {
await provider.openPage(sessionId, url, { parallel: false })
} catch (err) {
if (err instanceof Error && err.message === '[vitest] The provider was closed.') {
// provider is shutting down; abandon the operation gracefully
return
}
throw err
} Prevention
- Keep tests under the configured timeout so teardown does not interrupt them.
- Do not issue new browser operations in afterAll/globalTeardown.
- Handle SIGTERM in CI with a graceful period before SIGKILL.
When it happens
Trigger: Any browser operation (creating a context, opening/navigating a page) racing with provider.close() — e.g., a test still running when vitest is shutting down, SIGTERM handling, or a parallel test starting after close began.
Common situations: Long-running tests interrupted by SIGTERM/SIGINT or a test timeout; forceful teardown; flaky CI where the worker is killed mid-test; calling browser APIs in a hook that outlives teardown.
Related errors
- Page " " not found in browser.
- Cannot take a screenshot without a test path
- Browser is not initialized
- Browser provider is not defined for the project
- Cannot find iframe with id
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/dd742fa71633de0d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser-playwright/src/playwright.ts:656
}
async openPage(sessionId: string, url: string, options: { parallel: boolean }): Promise<void> {
debug?.('[%s][%s] creating the browser page for %s', sessionId, this.browserName, url)
const browserPage = await this.openBrowserPage(sessionId, options)
debug?.('[%s][%s] browser page is created, opening %s', sessionId, this.browserName, url)
await browserPage.goto(url, { timeout: 0 })
await this._throwIfClosing(browserPage)
}
private async _throwIfClosing(disposable?: { close: () => Promise<void> }) {
if (this.closing) {
debug?.('[%s] provider was closed, cannot perform the action on %s', this.browserName, String(disposable))
await disposable?.close()
this.pages.clear()
this.contexts.clear()
this.browser = null
this.browserPromise = null
throw new Error(`[vitest] The provider was closed.`)
}
}
async getCDPSession(sessionid: string): Promise<CDPSession> {
const page = this.getPage(sessionid)
const cdp = await page.context().newCDPSession(page)
return {
send: cdp.send.bind(cdp),
on: cdp.on.bind(cdp),
off: cdp.off.bind(cdp),
once: cdp.once.bind(cdp),
} as any // overloaded CDPSession type is too tricky in monorepo
}
async close(): Promise<void> {
process.off('SIGTERM', this.onSIGTERM)
debug?.('[%s] closing provider', this.browserName)View on GitHub (pinned to 1fa9837ec2)