{"id":"2ef4575264711adc","repo":"vitejs/vite","slug":"transport-must-implement-send-and-connect-when-inv","errorCode":null,"errorMessage":"transport must implement send and connect when invoke is not implemented","messagePattern":"transport must implement send and connect when invoke is not implemented","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/shared/moduleRunnerTransport.ts","lineNumber":68,"sourceCode":"        const result = await transport.invoke!({\n          type: 'custom',\n          event: 'vite:invoke',\n          data: {\n            id: 'send',\n            name,\n            data,\n          } satisfies InvokeSendData,\n        } satisfies CustomPayload)\n        if ('error' in result) {\n          throw reviveInvokeError(result.error)\n        }\n        return result.result\n      },\n    }\n  }\n\n  if (!transport.send || !transport.connect) {\n    throw new Error(\n      'transport must implement send and connect when invoke is not implemented',\n    )\n  }\n\n  const rpcPromises = new Map<\n    string,\n    {\n      resolve: (data: any) => void\n      reject: (data: any) => void\n      name: string\n      timeoutId?: ReturnType<typeof setTimeout>\n    }\n  >()\n\n  return {\n    ...transport,\n    connect({ onMessage, onDisconnection }) {\n      return transport.connect!({","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/shared/moduleRunnerTransport.ts#L50-L86","documentation":"Vite's module-runner transport abstraction supports two communication styles: a high-level invoke() RPC, or low-level send()/connect() message passing. When constructing the invokeable transport wrapper, if invoke is not implemented, Vite requires both send and connect so it can build the RPC layer on top of them. A transport object that implements neither invoke nor (send+connect) cannot communicate and is rejected.","triggerScenarios":"Providing a ModuleRunnerTransport object to a ModuleRunner that has no invoke method and is missing either send or connect (or both). This happens when creating a custom transport for the module runner (e.g. over a worker, iframe, or custom WebSocket) and omitting required methods.","commonSituations":"Building a custom SSR module-runner transport for a non-WebSocket channel (worker_threads, BroadcastChannel, postMessage). Providing a partial transport object where connect was forgotten. Copying a transport shape from an older Vite version where the requirements differed.","solutions":["Implement invoke on your transport (preferred for simpler integrations — a single async RPC function).","Or implement both send(data) and connect({ onMessage, onDisconnection }) so Vite can build RPC over them.","Use the built-in createWebSocketModuleRunnerTransport if communicating over a WebSocket, instead of a hand-rolled transport."],"exampleFix":"// before — transport missing required methods\nconst transport = {\n  send(data) { /* ... */ },\n  // connect missing, invoke missing\n}\n\n// after — implement invoke for a clean RPC interface\nconst transport = {\n  async invoke({ name, data }) {\n    const res = await myChannel.request(name, data)\n    return { result: res }\n  },\n}","handlingStrategy":"validation","validationCode":"// Validate a transport has a usable communication shape before constructing the runner\nfunction isValidTransport(t: any): boolean {\n  return (\n    typeof t.invoke === 'function' ||\n    (typeof t.send === 'function' && typeof t.connect === 'function')\n  )\n}\n\nif (!isValidTransport(myTransport)) {\n  throw new Error('Transport must implement invoke, or both send and connect')\n}","typeGuard":"function isInvokeTransport(t: any): t is { invoke: Function } {\n  return typeof t?.invoke === 'function'\n}\n\nfunction isSendConnectTransport(t: any): t is { send: Function; connect: Function } {\n  return typeof t?.send === 'function' && typeof t?.connect === 'function'\n}","tryCatchPattern":null,"preventionTips":["Implement invoke on custom transports for the simplest valid shape.","Prefer createWebSocketModuleRunnerTransport for WebSocket-based runners.","Unit-test custom transports by asserting they satisfy invoke or (send+connect)."],"tags":["module-runner","transport","rpc","configuration"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}