dotnet/runtime · error · Error
Please install `node-fetch` and `node-abort-controller` npm
Error message
Please install `node-fetch` and `node-abort-controller` npm packages to enable HTTP client support.
What it means
verifyEnvironment (called by httpCreateController and httpFetch) checks for global fetch and AbortController. On Node.js older than 18 these are not built in, so the .NET WASM HttpClient needs the node-fetch and node-abort-controller polyfills; without them any HTTP client use throws immediately.
Source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts:18
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import BuildConfiguration from "consts:configuration";
import type { VoidPtr, ControllablePromise } from "./types";
import { wrapAsCancelablePromise } from "./cancelable-promise";
import { ENVIRONMENT_IS_NODE } from "./per-module";
import { assertJsInterop } from "./utils";
import { MemoryViewType, Span } from "./marshaled-types";
import { dotnetLogger, dotnetAssert } from "./cross-module";
function verifyEnvironment() {
if (typeof globalThis.fetch !== "function" || typeof globalThis.AbortController !== "function") {
const message = ENVIRONMENT_IS_NODE
? "Please install `node-fetch` and `node-abort-controller` npm packages to enable HTTP client support."
: "This browser doesn't support fetch API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms";
throw new Error(message);
}
}
function commonAsserts(controller: HttpController) {
if (BuildConfiguration !== "Debug") {
return;
}
assertJsInterop();
dotnetAssert.check(controller, "expected controller");
}
export function httpSupportsStreamingRequest(): boolean {
// Detecting streaming request support works like this:
// If the browser doesn't support a particular body type, it calls toString() on the object and uses the result as the body.
// So, if the browser doesn't support request streams, the request body becomes the string "[object ReadableStream]".
// When a string is used as a body, it conveniently sets the Content-Type header to text/plain;charset=UTF-8.View on GitHub (pinned to 290d5ab72c)
Solutions
- Upgrade to Node 18+, which has global fetch and AbortController built in.
- Or: npm install node-fetch node-abort-controller and assign them to globalThis before invoking any HTTP API.
Example fix
// before (Node 16, no global fetch)
var ctrl = dotnet.INTERNAL.httpCreateController(); // throws
// after
const fetch = require("node-fetch"); globalThis.fetch = globalThis.fetch || fetch;
const { AbortController } = require("node-abort-controller"); globalThis.AbortController = globalThis.AbortController || AbortController;
var ctrl = dotnet.INTERNAL.httpCreateController(); Defensive patterns
Strategy: validation
Validate before calling
const isNode = typeof process !== "undefined" && process.versions?.node;
if (isNode && (typeof globalThis.fetch !== "function" || typeof globalThis.AbortController !== "function")) {
console.error("Install node-fetch & node-abort-controller (or use Node >= 18) before using HttpClient.");
} Prevention
- Target Node 18+ for .NET WASM HTTP work.
- Register fetch/AbortController polyfills at the very top of the Node entry script, before runtime init.
When it happens
Trigger: A .NET WASM app using HttpClient under Node.js (server-side, unit tests, SSR, build scripts) where globalThis.fetch or globalThis.AbortController is undefined.
Common situations: Node 14/16 hosting; Node-based test runners; forgetting to register the polyfills before the runtime initializes HTTP; SSR/prerender pipelines running on older Node.
Related errors
- Please install `node-fetch` and `node-abort-controller` npm
- This browser doesn't support fetch API. Please use a modern
- BrowserHttpWriteStream.Rejected
- NotImplementedException
- No fetch implementation available
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/19c2d72a7d3d6c50.
Report an issue: GitHub.