dotnet/runtime · error · Error
Please install `ws` npm package to enable networking…
Error message
Please install `ws` npm package to enable networking support.
What it means
Thrown by verifyEnvironment() inside ws_wasm_create() (src/mono/browser/runtime/web-socket.ts:35). The .NET WebAssembly runtime dispatches every System.Net.WebSockets call through ws_wasm_create; the guard first rejects shell engines, then checks typeof globalThis.WebSocket === 'function'. Under Node, the global WebSocket is absent from core, so the runtime refuses to create the socket and asks for the `ws` npm polyfill.
Solutions
- Run `npm install ws` in the host project; the runtime loader wires globalThis.WebSocket from the package when present.
- If WebSockets are not needed in the Node run, remove the managed code path that calls ClientWebSocket / System.Net.WebSockets.
- For a non-standard Node host, inject a WebSocket polyfill onto globalThis before dotnet.create().
Example fix
// before
const runtime = await dotnet.create();
// managed code: new ClientWebSocket().ConnectAsync(...) -> Error: Please install `ws`...
// after
// package.json: "dependencies": { "ws": "^8.x" }
// the runtime loader sets globalThis.WebSocket = ws when it detects Node
const runtime = await dotnet.create(); Defensive patterns
Strategy: validation
Validate before calling
function nodeHasWebSocket(): boolean {
return !ENVIRONMENT_IS_NODE || typeof globalThis.WebSocket === 'function';
}
if (!nodeHasWebSocket()) {
// install `ws` (npm install ws) before booting the runtime
} Type guard
function supportsWebSocket(g: typeof globalThis): g is typeof globalThis & { WebSocket: typeof WebSocket } {
return typeof g.WebSocket === 'function';
} Prevention
- Add `ws` to the host project's dependencies whenever the runtime may reach a WebSocket path under Node.
- Feature-detect globalThis.WebSocket before booting the runtime in Node.
- Keep WebSocket code out of Node-only prerender/SSR pipelines.
When it happens
Trigger: Any managed WebSocket path (ClientWebSocket.ConnectAsync/ReceiveAsync, SignalR, WebSocket.SendAsync) while the runtime is hosted in Node (ENVIRONMENT_IS_NODE true), e.g. dotnet wasm test runner, prerender, or an SSR host. verifyEnvironment() runs at the very start of ws_wasm_create before new WebSocket(uri) is attempted.
Common situations: Running .NET wasm unit tests or prerender under Node without the optional networking dependency; upgrading the runtime to a version that began asserting the Node environment; calling a SignalR client from a Node-hosted wasm component.
Related errors
- ERR22
- Please install `ws` npm package to enable networking…
- This browser doesn't support WebSocket API. Please use a…
- WebSockets are not supported in shell JS engine.
- Azure failed to download
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/320d0fe463475a86.
Report an issue: GitHub.
Appendix: source
Thrown at src/mono/browser/runtime/web-socket.ts:43
const wasm_ws_pending_close_promises = Symbol.for("wasm ws_pending_close_promises");
const wasm_ws_pending_send_promises = Symbol.for("wasm ws_pending_send_promises");
const wasm_ws_is_aborted = Symbol.for("wasm ws_is_aborted");
const wasm_ws_close_sent = Symbol.for("wasm wasm_ws_close_sent");
const wasm_ws_close_received = Symbol.for("wasm wasm_ws_close_received");
const wasm_ws_receive_status_ptr = Symbol.for("wasm ws_receive_status_ptr");
const ws_send_buffer_blocking_threshold = 65536;
const emptyBuffer = new Uint8Array();
function verifyEnvironment () {
if (ENVIRONMENT_IS_SHELL) {
throw new Error("WebSockets are not supported in shell JS engine.");
}
if (typeof globalThis.WebSocket !== "function") {
const message = ENVIRONMENT_IS_NODE
? "Please install `ws` npm package to enable networking support."
: "This browser doesn't support WebSocket API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms";
throw new Error(message);
}
}
export function ws_get_state (ws: WebSocketExtension): number {
if (ws.readyState != WebSocket.CLOSED)
return ws.readyState ?? -1;
const receive_event_queue = ws[wasm_ws_pending_receive_event_queue];
const queued_events_count = receive_event_queue.getLength();
if (queued_events_count == 0)
return ws.readyState ?? -1;
return ws[wasm_ws_close_sent] ? WebSocket.CLOSING : WebSocket.OPEN;
}
export function ws_wasm_create (uri: string, sub_protocols: string[] | null, receive_status_ptr: VoidPtr): WebSocketExtension {
verifyEnvironment();
assert_js_interop();
mono_assert(uri && typeof uri === "string", () => `ERR12: Invalid uri ${typeof uri}`);
let ws: WebSocketExtension;View on GitHub (pinned to 60108ba66e)