{"record":{"id":"4fa8987cd44f213c","repo":"moeru-ai/airi","slug":"no-websocket-constructor-is-available-pass-wscon","errorCode":null,"errorMessage":"No WebSocket constructor is available. Pass `wsConstructor` or use a connector.","messagePattern":"No WebSocket constructor is available\\. Pass `wsConstructor` or use a connector\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/better-ws/src/client/index.ts","lineNumber":872,"sourceCode":"      waiters.add(wait.emit)\n\n      void wait.promise.finally(() => {\n        waiters.delete(wait.emit)\n      }).catch(() => {})\n\n      return wait.promise\n    }\n  }\n\n  return client\n}\n\nfunction createSocketConnector(options: ClientUrlOptions): ClientConnector<string> {\n  return {\n    connect(events) {\n      const WsConstructor = options.wsConstructor ?? globalThis.WebSocket\n      if (!WsConstructor) {\n        throw new Error('No WebSocket constructor is available. Pass `wsConstructor` or use a connector.')\n      }\n\n      const ws = new WsConstructor(options.url, options.protocols)\n      return new Promise<ClientConnection<string>>((resolve, reject) => {\n        let opened = false\n        let failedBeforeOpen = false\n        ws.onopen = () => {\n          opened = true\n          resolve({\n            send: message => ws.send(message),\n            close: (code, reason) => ws.close(code, reason),\n          })\n        }\n        ws.onmessage = (event) => {\n          if (typeof event.data === 'string') {\n            events.message(event.data)\n            return\n          }","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/better-ws/src/client/index.ts#L854-L890","documentation":"The socket connector resolves the WebSocket constructor as options.wsConstructor ?? globalThis.WebSocket. If both are undefined it refuses to proceed because there is no way to open a socket. Browsers define globalThis.WebSocket natively, but many non-browser runtimes (Node without the `ws` package, custom embeddings, some test/SSR environments) do not.","triggerScenarios":"Using the better-ws client in Node.js without installing/importing `ws`; running in an SSR or test environment where globalThis.WebSocket is undefined; targeting a runtime that exposes WebSocket under a different global; the user passed a falsy wsConstructor.","commonSituations":"Server-side subscriptions, integration tests in jsdom (which lacks WebSocket unless polyfilled), Deno/bun-detection differences, or a bundler that stripped the WebSocket reference.","solutions":["Install `ws` and pass wsConstructor: import WebSocket from 'ws'; new Client({ url, wsConstructor: WebSocket }).","Use a custom ClientConnector (e.g. a node ws connector) instead of the default socket connector.","Polyfill globalThis.WebSocket in the test/SSR environment.","Detect runtime support and skip the connection when no constructor is available."],"exampleFix":"// before\nconst client = createClient({ url: 'wss://example.com' })\n// in Node: throws 'No WebSocket constructor is available...'\n\n// after\nimport WebSocket from 'ws'\nconst client = createClient({ url: 'wss://example.com', wsConstructor: WebSocket as any })","handlingStrategy":"validation","validationCode":"function resolveWsConstructor(): typeof WebSocket | undefined {\n  return options.wsConstructor ?? (typeof globalThis !== 'undefined' ? globalThis.WebSocket : undefined)\n}\nif (!resolveWsConstructor()) {\n  throw new Error('Install \\'ws\\' and pass wsConstructor, or provide a custom connector')\n}","typeGuard":"function isWsConstructor(fn: unknown): fn is new (url: string, protocols?: string | string[]) => WebSocket {\n  return typeof fn === 'function'\n}","tryCatchPattern":"try {\n  return createClient({ url, wsConstructor: WebSocketCtor })\n}\ncatch (err) {\n  if (/No WebSocket constructor/i.test((err as Error).message)) {\n    // switch to a custom connector or polyfill globalThis.WebSocket\n    throw new Error('Provide wsConstructor (e.g. from \\'ws\\') for this runtime')\n  }\n  throw err\n}","preventionTips":["In Node, always pass wsConstructor from the `ws` package.","Feature-detect globalThis.WebSocket before relying on the default connector.","Polyfill WebSocket in jsdom/SSR test environments."],"tags":["websocket","node","ssr","runtime","constructor"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}