dotnet/runtime · critical · Error

Failed to load WebAssembly module. HTTP status: ${res?.statu

Error message

Failed to load WebAssembly module. HTTP status: ${res?.status} ${res?.statusText}

What it means

Thrown inside instantiateWasm -> checkResponseOk when the fetch of the native dotnet.native.wasm binary resolves with ok === false. The HTTP status and statusText are included so a 404, 403, or 500 is distinguishable. This is the top-level WASM module fetch; failure aborts runtime startup.

Source

Thrown at src/native/libs/Common/JavaScript/host/assets.ts:179

            const data = await res.arrayBuffer();
            module = await WebAssembly.compile(data);
            instance = await WebAssembly.instantiate(module, imports);
        } else {
            const instantiated = await WebAssembly.instantiateStreaming(wasmPromise, imports);
            instance = instantiated.instance;
            module = instantiated.module;
        }
        return { instance, module };
    } catch (err) {
        _ems_.dotnetApi.exit(1, err);
        throw err;
    }

    async function checkResponseOk(wasmPromise: Promise<Response> | undefined): Promise<Response & { isStreamingOk?: boolean }> {
        _ems_.dotnetAssert.check(wasmPromise, "WASM binary promise was not initialized");
        const res = (await wasmPromise) as Response & { isStreamingOk?: boolean };
        if (!res || res.ok === false) {
            throw new Error(`Failed to load WebAssembly module. HTTP status: ${res?.status} ${res?.statusText}`);
        }
        res.isStreamingOk = typeof globalThis.Response === "function" && res instanceof globalThis.Response;
        const contentType = res.headers && res.headers.get ? res.headers.get("Content-Type") : undefined;
        if (_ems_.ENVIRONMENT_IS_WEB && contentType !== "application/wasm") {
            _ems_.dotnetLogger.warn("WebAssembly resource does not have the expected content type \"application/wasm\", so falling back to slower ArrayBuffer instantiation.");
            res.isStreamingOk = false;
        }
        return res;
    }
}

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Open the exact failing URL (status + statusText are in the message) in a browser/Network tab to confirm 404/403/500.
  2. Verify the published _framework folder contains dotnet.native.wasm and the served path matches <base href>.
  3. For 401/403, fix auth/CORS headers and CDN access rules for the wasm asset.
  4. Ensure the host sends Content-Type: application/wasm so streaming instantiation works (avoids a slower fallback and some rejections).

Example fix

// before: misconfigured base href causes 404 on wasm
<script src="/framework/dotnet.runtime.js"></script>
// after: base href + asset path match publish layout
<base href="/app/" />
<script src="_framework/dotnet.runtime.js"></script>
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await instantiateWasm(wasmPromise, imports);
} catch (e) {
  const m = /HTTP status: (\d{3})/.exec(String(e.message));
  const status = m ? +m[1] : 0;
  if (status === 404) throw new Error('dotnet.native.wasm not found; check <base href> and publish output.', { cause: e });
  if (status === 401 || status === 403) throw new Error('Auth/CORS blocked the wasm asset.', { cause: e });
  throw e;
}

Prevention

When it happens

Trigger: instantiateWasm(wasmPromise, imports) where the Response.status is >= 400: file missing (404), auth forbidden (401/403), server error (5xx), or a Response that is undefined/null.

Common situations: Wrong deploy path or base-href so _framework/_bin/dotnet.native.wasm 404s; reverse proxy/CDN stripping the asset; publish output missing the wasm (truncated deploy); CORS preflight rejection; dev server not serving the binary directory.

Related errors


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