{"record":{"id":"668114d48c1bfa6f","repo":"vitest-dev/vitest","slug":"tester-rpc-rpcid-was-not-established","errorCode":null,"errorMessage":"Tester RPC \"${rpcId}\" was not established.","messagePattern":"Tester RPC \"(.+?)\" was not established\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/node/projectParent.ts","lineNumber":221,"sourceCode":"    const provider = browser.provider\n    if (!provider) {\n      throw new Error(`Browser provider is not defined for the project \"${browserSession.project.name}\".`)\n    }\n    if (!provider.getCDPSession) {\n      throw new Error(`CDP is not supported by the provider \"${provider.name}\".`)\n    }\n\n    const session = await this.cdpSessionsPromises.get(rpcId) ?? await (async () => {\n      const promise = provider.getCDPSession!(sessionId).finally(() => {\n        this.cdpSessionsPromises.delete(rpcId)\n      })\n      this.cdpSessionsPromises.set(rpcId, promise)\n      return promise\n    })()\n\n    const rpc = (browser.state as BrowserServerState).testers.get(rpcId)\n    if (!rpc) {\n      throw new Error(`Tester RPC \"${rpcId}\" was not established.`)\n    }\n\n    const handler = new BrowserServerCDPHandler(session, rpc)\n    this.cdps.set(\n      rpcId,\n      handler,\n    )\n    return handler\n  }\n\n  removeCDPHandler(sessionId: string): void {\n    this.cdps.delete(sessionId)\n  }\n\n  async formatScripts(scripts: BrowserScript[] | undefined): Promise<HtmlTagDescriptor[]> {\n    if (!scripts?.length) {\n      return []\n    }","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/node/projectParent.ts#L203-L239","documentation":"After obtaining a CDPSession, ensureCDPHandler looks up the corresponding tester RPC connection in (browser.state as BrowserServerState).testers using rpcId. The testers map is populated when a tester iframe connects over WebSocket. If no tester has registered under that rpcId, the CDP handler cannot be wired to a target page.","triggerScenarios":"Issuing a CDP request for an rpcId whose tester WebSocket never connected, already disconnected, or connected under a different rpcId. Common during flaky loads, navigation away from the tester iframe, or when the tester crashed before registering.","commonSituations":"Browser UI issuing CDP commands before the tester finished loading; tester crashed on a syntax error so no WS connection was made; network/proxy issue dropping the tester WS handshake; reusing an rpcId from a previous run.","solutions":["Reload the tester iframe so it reconnects and re-registers under its rpcId before issuing CDP commands.","Check the browser console and server logs for tester load failures (module errors, 404s) that prevent WS registration.","Verify rpcId is the current tester's id, not a stale one from a previous run.","Ensure no middleware/proxy strips the WS upgrade between the tester and the Vitest server."],"exampleFix":"// before\nconst handler = await parent.ensureCDPHandler(sessionId, staleRpcId)\n// after - read the live rpc id from the testers map\nconst rpcId = [...(browser.state as BrowserServerState).testers.keys()][0]!\nconst handler = await parent.ensureCDPHandler(sessionId, rpcId)","handlingStrategy":"validation","validationCode":"function testerRpcLive(testers: Map<string, unknown>, rpcId: string): boolean {\n  return testers.has(rpcId)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure the tester iframe finished loading before issuing CDP commands.","Watch the server log for tester load failures (404, module errors).","Always derive rpcId from the live testers map, never cache it."],"tags":["cdp","tester","websocket","rpc","browser"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}