{"id":"b0bb8f464c398d31","repo":"vitejs/vite","slug":"send-was-called-before-connect","errorCode":null,"errorMessage":"send was called before connect","messagePattern":"send was called before connect","errorType":"exception","errorClass":"SendBeforeConnectError","httpStatus":null,"severity":"error","filePath":"packages/vite/src/shared/moduleRunnerTransport.ts","lineNumber":240,"sourceCode":"      ? {\n          async disconnect() {\n            if (!isConnected) return\n            if (connectingPromise) {\n              await connectingPromise\n            }\n            isConnected = false\n            await invokeableTransport.disconnect!()\n          },\n        }\n      : {}),\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 {","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/shared/moduleRunnerTransport.ts#L222-L258","documentation":"Vite's normalized module-runner transport tracks a connection state. After wrapping, send() checks isConnected: if not connected and no connect() is in flight (no connectingPromise), it throws SendBeforeConnectError because messages cannot be delivered on an unestablished channel. This guards against losing messages that are sent before the transport's connect() resolves.","triggerScenarios":"Calling transport.send(data) on a normalized module-runner transport before connect() has been awaited (and no connect is currently pending). Happens when a module runner or consumer fires a message synchronously at startup before awaiting the transport connection.","commonSituations":"A custom module-runner transport where the runner starts importing modules (triggering sends) before the underlying channel (WebSocket, worker) is open. Race conditions in startup ordering where the HMR/RPC send is dispatched during construction. Test harnesses that create a runner and immediately send without connecting.","solutions":["Await transport.connect() before sending — ensure startup code awaits the connection promise.","If using the ModuleRunner, let it manage connect ordering; do not call send on the raw transport yourself.","For custom transports, set up the channel synchronously (e.g. readyState OPEN) or await its open event before the runner sends."],"exampleFix":"// before — sending before the connection is established\nconst transport = normalizeModuleRunnerTransport(myTransport)\nawait transport.send({ type: 'custom', event: 'ping', data: {} }) // throws\n\n// after — connect first\nconst transport = normalizeModuleRunnerTransport(myTransport)\nawait transport.connect()\nawait transport.send({ type: 'custom', event: 'ping', data: {} })","handlingStrategy":"validation","validationCode":"// Ensure connect is awaited before any send\nawait transport.connect()\n// now safe to send\nawait transport.send(data)","typeGuard":null,"tryCatchPattern":"import { SendBeforeConnectError } from 'vite/module-runner'\n\ntry {\n  await transport.send(data)\n} catch (e) {\n  if (e instanceof SendBeforeConnectError) {\n    await transport.connect()\n    await transport.send(data)\n  } else {\n    throw e\n  }\n}","preventionTips":["Always await transport.connect() before sending.","Let the ModuleRunner manage connect/send ordering; avoid manual sends.","Where possible, make the underlying channel open synchronously."],"tags":["module-runner","transport","connection","ordering"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}