vitest-dev/vitest · error · Error
Cannot find iframe with id
Error message
Cannot find iframe with id ${event.iframeId} What it means
The browser orchestrator multiplexes tests across iframes keyed by iframeId. sendEventToIframe looks up the iframe in this.iframes; if it was removed (removeIframe deletes the entry) or never registered, it throws. Messages are dispatched to tester iframes during normal test execution (prepare, run, collect).
Solutions
- Avoid navigating/reloading the iframe from test code: call `event.preventDefault()` on form submits and use memory-based routing for SPA routers.
- Ensure dependencies are optimized (configure `optimizeDeps`) so the tester iframe does not reload.
- If seen sporadically in CI, check for tester crashes/unhandled errors that remove the iframe.
- Report persistent occurrences with a reproduction — this often indicates a race the orchestrator should tolerate.
Example fix
// before
form.dispatchEvent(new Event('submit')) // browser reloads iframe -> orchestrator removes it
// after
form.addEventListener('submit', (e) => e.preventDefault())
form.dispatchEvent(new Event('submit')) Defensive patterns
Strategy: try-catch
Validate before calling
// there is no public pre-check; reduce likelihood by avoiding iframe reloads:
form.addEventListener('submit', (e) => e.preventDefault())
await expect(page.getByRole('button')).toBeVisible() // wait for tester readiness Try / catch
// orchestrator-internal; if surfacing in custom UI integration:
try {
await sendEventToIframe(event)
} catch (err) {
if (err instanceof Error && err.message.startsWith('Cannot find iframe')) {
// iframe was removed; re-register or skip this event
return
}
throw err
} Prevention
- Prevent iframe navigation/reload in tests (preventDefault on submit, memory routing).
- Ensure optimizeDeps includes all deps so the tester does not reload.
- Handle tester errors promptly so the orchestrator does not target a removed iframe.
When it happens
Trigger: The orchestrator tries to send an event (prepare/run/etc.) to an iframe that has been removed (tester crashed, reloaded, or was torn down) or whose id was never registered (typo, race during registration). Common when an iframe reloads mid-test and is removed before a queued message is dispatched.
Common situations: Iframe navigated/reloaded during a test (e.g., form submit without preventDefault, router location change) triggering removal; tester crash; timing race where an event is queued before the iframe's onload registers it.
Related errors
- Cannot find iframe element. This is a bug in Vitest…
- Method "frameLocator" is not supported by the
- Page " " not found in browser.
- [vitest] The provider was closed.
- Access denied to " ". See Vite config documentation for…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/e17be4af39f7bef8.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/client/orchestrator.ts:486
}
await client.rpc.onUnhandledError(
{
name: 'Unexpected Event',
message: `Unexpected event: ${(e.data as any).event}`,
},
'Unexpected Event',
)
}
}
}
private iframeEvents = new WeakMap<HTMLIFrameElement, Set<string>>()
private async sendEventToIframe(event: IframeChannelOutgoingEvent): Promise<void> {
const iframe = this.iframes.get(event.iframeId)
if (!iframe) {
throw new Error(`Cannot find iframe with id ${event.iframeId}`)
}
let events = this.iframeEvents.get(iframe)
if (!events) {
events = new Set()
this.iframeEvents.set(iframe, events)
}
events.add(event.event)
const messageId = this.messageId++
channel.postMessage({ ...event, messageId } satisfies IframeReceivedEvent)
return new Promise<void>((resolve, reject) => {
let ackTimer: ReturnType<typeof setTimeout>
const cleanupEvents = () => {
clearTimeout(ackTimer)
channel.removeEventListener('message', onReceived)
this.eventTarget.removeEventListener('iframeerror', onError)View on GitHub (pinned to 1fa9837ec2)