dotnet/runtime · critical · Error

No fetch implementation available

Error message

No fetch implementation available

What it means

fetchLike (loader/polyfills.ts) is the last-resort fetch implementation. It tries: Node fs for file:// and missing-fetch cases, globalThis.fetch in browser/node, and the global read() function in JS shells. If none of these branches apply (no fetch, not Node, no read), it throws 'No fetch implementation available'.

Source

Thrown at src/native/libs/Common/JavaScript/loader/polyfills.ts:136

            const isText = expectedContentType && (expectedContentType.startsWith("application/json") || expectedContentType.startsWith("text/plain"));
            const arrayBuffer = read(url, isText ? "utf8" : "binary");
            return responseLike(url, arrayBuffer, {
                status: 200,
                statusText: "OK",
                headers: {
                    "Content-Length": isText ? arrayBuffer.length : arrayBuffer.byteLength.toString(),
                    "Content-Type": expectedContentType || "application/octet-stream"
                }
            });
        }
    } catch (e: any) {
        return responseLike(url, null, {
            status: 500,
            statusText: "ERR28: " + e,
            headers: {},
        });
    }
    throw new Error("No fetch implementation available");
}

export function responseLike(url: string, body: ArrayBuffer | string | null, options: ResponseInit): Response {
    if (typeof globalThis.Response === "function") {
        const response = new Response(body, options);

        // Best-effort alignment with the fallback object shape:
        // only define `url` if it does not already exist on the response.
        if (typeof (response as any).url === "undefined") {
            try {
                Object.defineProperty(response, "url", { value: url });
            } catch {
                // Ignore if the implementation does not allow redefining `url`
            }
        }

        return response;
    }

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Provide globalThis.fetch before bootstrapping: install node-fetch, undici, or the host's native fetch.
  2. If running under Node, ensure ENVIRONMENT_IS_NODE detection works (process.versions.node present) so the fs branch engages.
  3. For JS shells, expose a global read() function compatible with the emscripten signature.
  4. Use a loadBootResource callback (withResourceLoader) to supply your own fetch returning Response objects.

Example fix

// before — no fetch in custom host
const dotnet = await dotnet.create(); // throws 'No fetch implementation available'

// after — install fetch
const fetch = require('node-fetch');
globalThis.fetch = fetch;
const dotnet = await dotnet.create();
Defensive patterns

Strategy: fallback

Validate before calling

if (typeof globalThis.fetch !== 'function' && typeof globalThis.require !== 'function') {
  throw new Error('No fetch detected — install node-fetch or provide a global fetch before boot');
}

Type guard

function hasFetch(g: any): g is { fetch: typeof fetch } {
  return typeof g?.fetch === 'function';
}

Prevention

When it happens

Trigger: Booting the loader in an environment that has no globalThis.fetch, is not detected as Node (so _nodeFs is undefined), and does not provide a global read() function. The loader cannot download any asset.

Common situations: Running inside an embedded/worker runtime that stripped fetch; a test harness (jsdom) without fetch configured; a sandboxed VM context missing both fetch and require; a custom host that set ENVIRONMENT_IS_NODE=false but did not provide fetch.

Related errors


AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06). Data as JSON: /api/errors/1cbfc6518d5e2e6a. Report an issue: GitHub.