{"record":{"id":"5019d18464787640","repo":"dotnet/aspnetcore","slug":"websocket-is-not-supported-in-your-environment","errorCode":null,"errorMessage":"'WebSocket' is not supported in your environment.","messagePattern":"'WebSocket' is not supported in your environment\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/ts/signalr/src/HttpConnection.ts","lineNumber":529,"sourceCode":"                        const message = \"Failed to select transport before stop() was called.\";\n                        this._logger.log(LogLevel.Debug, message);\n                        return Promise.reject(new AbortError(message));\n                    }\n                }\n            }\n        }\n\n        if (transportExceptions.length > 0) {\n            return Promise.reject(new AggregateErrors(`Unable to connect to the server with any of the available transports. ${transportExceptions.join(\" \")}`, transportExceptions));\n        }\n        return Promise.reject(new Error(\"None of the transports supported by the client are supported by the server.\"));\n    }\n\n    private _constructTransport(transport: HttpTransportType): ITransport {\n        switch (transport) {\n            case HttpTransportType.WebSockets:\n                if (!this._options.WebSocket) {\n                    throw new Error(\"'WebSocket' is not supported in your environment.\");\n                }\n                return new WebSocketTransport(this._httpClient, this._accessTokenFactory, this._logger, this._options.logMessageContent!,\n                    this._options.WebSocket, this._options.headers || {});\n            case HttpTransportType.ServerSentEvents:\n                if (!this._options.EventSource) {\n                    throw new Error(\"'EventSource' is not supported in your environment.\");\n                }\n                return new ServerSentEventsTransport(this._httpClient, this._httpClient._accessToken, this._logger, this._options);\n            case HttpTransportType.LongPolling:\n                return new LongPollingTransport(this._httpClient, this._logger, this._options);\n            default:\n                throw new Error(`Unknown transport: ${transport}.`);\n        }\n    }\n\n    private _startTransport(url: string, transferFormat: TransferFormat): Promise<void> {\n        this.transport!.onreceive = this.onreceive;\n        if (this.features.reconnect) {","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/ts/signalr/src/HttpConnection.ts#L511-L547","documentation":"_constructTransport throws if WebSockets was selected but options.WebSocket is falsy. options.WebSocket is normally populated from the global WebSocket (browser) or the 'ws' npm module (Node); if neither resolved, the runtime has no WebSocket implementation to use.","triggerScenarios":"Transport selection picks HttpTransportType.WebSockets (explicitly or via auto-negotiate) but options.WebSocket was never set. The constructor only assigns WebSocket if global WebSocket exists or, under Platform.isNode, the 'ws' module loaded successfully.","commonSituations":"Running in Node without 'ws' installed (it's an optional peer dep). Running in an environment that lacks a global WebSocket (older browsers, some embedded engines). Bundler stripped the dynamic require('ws'). The user explicitly set transport: WebSockets in an environment that cannot support it.","solutions":["Install 'ws' (npm install ws) when running on Node, or upgrade to Node 22+ where WebSocket is built-in.","Provide a WebSocket implementation explicitly: withUrl(url, { WebSocket: MyWSImpl }).","Fall back to a transport the environment supports (ServerSentEvents or LongPolling) by setting transport accordingly.","Ensure your bundler does not tree-shake the global WebSocket polyfill."],"exampleFix":"// before: Node without 'ws'\nconst conn = new signalR.HubConnectionBuilder()\n  .withUrl(url, { transport: signalR.HttpTransportType.WebSockets })\n  .build();\n\n// after: supply an implementation\nimport WebSocket from \"ws\";\nconst conn = new signalR.HubConnectionBuilder()\n  .withUrl(url, { transport: signalR.HttpTransportType.WebSockets, WebSocket })\n  .build();","handlingStrategy":"validation","validationCode":"function resolveWebSocket(): typeof WebSocket | undefined {\n  if (typeof WebSocket !== \"undefined\") return WebSocket;\n  try { return require(\"ws\"); } catch { return undefined; }\n}\nconst WS = resolveWebSocket();\nif (!WS && process.versions?.node) await import(\"ws\");","typeGuard":"function hasWebSocketImpl(opts: signalR.IHttpConnectionOptions): boolean {\n  return typeof opts.WebSocket === \"function\" || typeof WebSocket !== \"undefined\";\n}","tryCatchPattern":"try { await connection.start(); }\ncatch (e) {\n  if (e instanceof Error && /'WebSocket' is not supported/.test(e.message)) {\n    opts.WebSocket = require(\"ws\");\n    return newConnection(opts);\n  }\n  throw e;\n}","preventionTips":["Install 'ws' on Node, or run Node 22+ with built-in WebSocket.","Pass WebSocket explicitly in options when bundling for non-browser targets.","If the environment truly lacks WebSockets, fall back to LongPolling."],"tags":["transport","websocket","environment","node","configuration"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}