dotnet/runtime · critical · Error

No fetch implementation available

Error message

No fetch implementation available

What it means

Thrown by fetch_like in polyfills.ts as the final fallthrough: the caller is not in a Node context, globalThis.fetch is not a function, and the global read function (V8 shell) is absent. No mechanism remains to fetch the resource, so the loader aborts.

Solutions

  1. Provide a fetch polyfill on globalThis.fetch before starting the runtime (whatwg-fetch, node-fetch, undici, or a custom shim).
  2. If embedding in a shell, set loaderHelpers.fetch_like to your own fetch implementation via the module config.
  3. Correct the environment detection so ENVIRONMENT_IS_NODE/WEB/SHELL matches your host and the right fetch path is taken.

Example fix

// before: no fetch in custom host
// after: install a shim before booting the runtime
globalThis.fetch = (url, init) => myHttpLib.request(url, init);
Defensive patterns

Strategy: fallback

Validate before calling

// before booting, ensure some fetch exists
if (typeof globalThis.fetch !== 'function' && typeof globalThis.read !== 'function') {
  throw new Error('No fetch available; install a polyfill');
}

Type guard

function hasFetchLike(): boolean {
  return typeof globalThis.fetch === 'function' || typeof (globalThis as any).read === 'function';
}

Prevention

When it happens

Trigger: Running the wasm runtime in a bare JS engine (V8/d8, JavaScriptCore shell, an embedded runtime) that provides neither fetch nor the d8 read() global; an environment where globalThis.fetch was deleted or never provided; a misdetected environment (ENVIRONMENT_IS_NODE/WEB/SHELL all false).

Common situations: Custom embedding of the runtime in a non-browser host without providing a fetch implementation; sandboxing that removes fetch; an engine detection bug in the host.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/2f6515a452b91ca3. Report an issue: GitHub.

Appendix: source

Thrown at src/mono/browser/runtime/loader/polyfills.ts:179

            url,
            status: 500,
            headers: {
                length: 0,
                get: () => null
            },
            statusText: "ERR28: " + e,
            arrayBuffer: () => {
                throw e;
            },
            json: () => {
                throw e;
            },
            text: () => {
                throw e;
            }
        };
    }
    throw new Error("No fetch implementation available");
}

// context: the loadBootResource extension point can return URL/string which is unqualified.
// For example `xxx/a.js` and we have to make it absolute
// For compatibility reasons, it's based of document.baseURI even for JS modules like `./xxx/a.js`, which normally use script directory of a caller of `import`
// Script directory in general doesn't match document.baseURI
export function makeURLAbsoluteWithApplicationBase (url: string) {
    mono_assert(typeof url === "string", "url must be a string");
    if (!isPathAbsolute(url) && url.indexOf("./") !== 0 && url.indexOf("../") !== 0 && globalThis.URL && globalThis.document && globalThis.document.baseURI) {
        url = (new URL(url, globalThis.document.baseURI)).toString();
    }
    return url;
}

function normalizeFileUrl (filename: string) {
    // unix vs windows
    // remove query string
    return filename.replace(/\\/g, "/").replace(/[?#].*/, "");

View on GitHub (pinned to 60108ba66e)