{"record":{"id":"b2c0391291269a7f","repo":"vitejs/vite","slug":"invoke-was-called-before-connect","errorCode":null,"errorMessage":"invoke was called before connect","messagePattern":"invoke was called before connect","errorType":"exception","errorClass":"SendBeforeConnectError","httpStatus":null,"severity":"error","filePath":"packages/vite/src/shared/moduleRunnerTransport.ts","lineNumber":250,"sourceCode":"      : {}),\n    async send(data) {\n      if (!invokeableTransport.send) return\n\n      if (!isConnected) {\n        if (connectingPromise) {\n          await connectingPromise\n        } else {\n          throw new SendBeforeConnectError('send was called before connect')\n        }\n      }\n      await invokeableTransport.send(data)\n    },\n    async invoke(name, data) {\n      if (!isConnected) {\n        if (connectingPromise) {\n          await connectingPromise\n        } else {\n          throw new SendBeforeConnectError('invoke was called before connect')\n        }\n      }\n      return invokeableTransport.invoke(name, data)\n    },\n  }\n}\n\nexport class SendBeforeConnectError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = 'SendBeforeConnectError'\n  }\n}\n\nexport const createWebSocketModuleRunnerTransport = (options: {\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  createConnection: () => WebSocket\n  pingInterval?: number","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/vitejs/vite/blob/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/shared/moduleRunnerTransport.ts#L232-L268","documentation":"Thrown by the normalized transport's invoke() when called before connect() has completed and there is no in-flight connecting promise. invoke() needs the transport to be connected so the RPC request/response round-trip can complete; invoking earlier rejects immediately.","triggerScenarios":"Calling transport.invoke(name, data) before awaiting transport.connect(). Throws SendBeforeConnectError at moduleRunnerTransport.ts:250 under the same conditions as the send guard.","commonSituations":"Custom runner bootstrap that issues an RPC immediately. Calling invoke during construction before the WebSocket/emitter is ready. Forgetting to await an async connect in setup.","solutions":["Await transport.connect() before any invoke call.","Let the ModuleRunner own connection lifecycle — avoid calling transport.invoke manually outside the runner.","Catch SendBeforeConnectError (error.name === 'SendBeforeConnectError') and retry once connect resolves."],"exampleFix":"// before\nconst res = await transport.invoke('fetchModule', [id]) // throws if not connected\n// after\nawait transport.connect()\nconst res = await transport.invoke('fetchModule', [id])","handlingStrategy":"validation","validationCode":"await transport.connect()\nawait transport.invoke(name, data)","typeGuard":null,"tryCatchPattern":"try {\n  await transport.invoke(name, data)\n} catch (e) {\n  if (e?.name === 'SendBeforeConnectError') {\n    await transport.connect()\n    await transport.invoke(name, data)\n  } else throw e\n}","preventionTips":["Await connect() before any invoke call.","Route RPC through the ModuleRunner rather than calling transport.invoke directly."],"tags":["module-runner","transport","lifecycle"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}