vitest-dev/vitest · error · Error

Tester RPC "${rpcId}" was not established.

Error message

Tester RPC "${rpcId}" was not established.

What it means

After obtaining a CDP session, `ensureCDPHandler` looks up the tester RPC channel by `rpcId` in `browser.state.testers`. The tester RPC is registered when the tester websocket connects (type='tester' in the upgrade handler). If no tester is registered for that rpcId, the CDP handler has nowhere to forward events.

Source

Thrown at packages/browser/src/node/projectParent.ts:221

    const provider = browser.provider
    if (!provider) {
      throw new Error(`Browser provider is not defined for the project "${browserSession.project.name}".`)
    }
    if (!provider.getCDPSession) {
      throw new Error(`CDP is not supported by the provider "${provider.name}".`)
    }

    const session = await this.cdpSessionsPromises.get(rpcId) ?? await (async () => {
      const promise = provider.getCDPSession!(sessionId).finally(() => {
        this.cdpSessionsPromises.delete(rpcId)
      })
      this.cdpSessionsPromises.set(rpcId, promise)
      return promise
    })()

    const rpc = (browser.state as BrowserServerState).testers.get(rpcId)
    if (!rpc) {
      throw new Error(`Tester RPC "${rpcId}" was not established.`)
    }

    const handler = new BrowserServerCDPHandler(session, rpc)
    this.cdps.set(
      rpcId,
      handler,
    )
    return handler
  }

  removeCDPHandler(sessionId: string): void {
    this.cdps.delete(sessionId)
  }

  async formatScripts(scripts: BrowserScript[] | undefined): Promise<HtmlTagDescriptor[]> {
    if (!scripts?.length) {
      return []
    }

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Ensure the tester page is open and connected before issuing CDP calls.
  2. Verify the rpcId passed to `ensureCDPHandler` matches the one used by the tester websocket.
  3. Retry after a short delay if the tester is still loading — but prefer waiting for an explicit ready signal.

Example fix

// before — CDP call before tester connected
await sendCdpEvent(sessionId, 'Page.reload')

// after — wait for tester ready
await page.waitForLoadState?.() // or your framework's ready hook
await sendCdpEvent(sessionId, 'Page.reload')
Defensive patterns

Strategy: validation

Validate before calling

function testerRpcReady(state: { testers: Map<string, unknown> }, rpcId: string): boolean {
  return state.testers.has(rpcId)
}

Prevention

When it happens

Trigger: Requesting a CDP handler for an `rpcId` whose tester websocket never connected, or already disconnected (the `close` handler deletes it).

Common situations: CDP call before the tester iframe finished connecting; tester tab crashed/closed between the CDP request and handler creation; rpcId mismatch between orchestrator and tester connections.

Related errors


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