dotnet/runtime · error · Error
WebSockets are not supported in shell JS engine.
Error message
WebSockets are not supported in shell JS engine.
What it means
Thrown by verifyEnvironment() in web-socket.ts when the runtime detects ENVIRONMENT_IS_SHELL - i.e. it is running in a bare JS shell (d8, V8/jsshell, js shell) rather than a browser or Node. JS shells do not provide a WebSocket implementation, so any attempt to create a WebSocket is blocked before construction.
Solutions
- Run the networking code under Node (install the 'ws' package) or a real browser instead of a JS shell.
- Skip/guard WebSocket-using code paths when ENVIRONMENT_IS_SHELL is true.
- If you must use a shell, mock globalThis.WebSocket before the call - though note the shell guard fires first, so you would need to disable the shell path via a custom build.
Example fix
// before - run in d8/jsshell
ws_wasm_create(uri, subProtocols, ptr); // throws
// after - detect and skip
if (!ENVIRONMENT_IS_SHELL) { ws_wasm_create(uri, subProtocols, ptr); } Defensive patterns
Strategy: validation
Validate before calling
import { ENVIRONMENT_IS_SHELL } from './globals';
function canUseWebSocket(): boolean {
return !ENVIRONMENT_IS_SHELL && typeof globalThis.WebSocket === 'function';
}
if (canUseWebSocket()) { ws_wasm_create(uri, subProtocols, ptr); } Type guard
function supportsWebSocket(): boolean {
return !ENVIRONMENT_IS_SHELL && typeof globalThis.WebSocket === 'function';
} Prevention
- Gate networking code behind an environment check before invoking WebSocket APIs.
- Prefer Node or a browser for integration tests that need WebSockets.
- In Node, install the 'ws' package so the WebSocket global is present.
When it happens
Trigger: Calling ws_wasm_create (which calls verifyEnvironment) while dotnet Wasm is hosted in a JS shell such as d8 or the V8 shell. The first guard on line 36-38 throws before the WebSocket global is even inspected.
Common situations: Running automated tests or build scripts that load the Wasm runtime in a JS shell and then exercise networking; using the runtime under a REPL/shell for quick experiments; CI that uses a shell engine instead of Node or a browser.
Related errors
- WebSockets are not supported in shell JS engine.
- Azure failed to download
- BrowserHttpWriteStream.Rejected
- BrowserHttpWriteStream.Rejected
- Couldn't determine newest 'main' git hash
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/082c049c07e21121.
Report an issue: GitHub.
Appendix: source
Thrown at src/mono/browser/runtime/web-socket.ts:37
const wasm_ws_pending_send_buffer_type = Symbol.for("wasm ws_pending_send_buffer_type");
const wasm_ws_pending_receive_event_queue = Symbol.for("wasm ws_pending_receive_event_queue");
const wasm_ws_pending_receive_promise_queue = Symbol.for("wasm ws_pending_receive_promise_queue");
const wasm_ws_pending_open_promise = Symbol.for("wasm ws_pending_open_promise");
const wasm_ws_pending_open_promise_used = Symbol.for("wasm wasm_ws_pending_open_promise_used");
const wasm_ws_pending_error = Symbol.for("wasm wasm_ws_pending_error");
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;
}View on GitHub (pinned to 60108ba66e)