dotnet/aspnetcore · critical · Error

This browser does not support WebAssembly.

Error message

This browser does not support WebAssembly.

What it means

`importDotnetJs` is the entry point for loading the .NET WebAssembly runtime in a Blazor WebAssembly app. It first checks that the browser exposes a usable `WebAssembly` global and that `WebAssembly.validate` exists; if not, the runtime cannot be instantiated and startup aborts with this error. It is a hard environment prerequisite, not a recoverable config issue.

Solutions

  1. Require a modern, WASM-capable browser and communicate that to users (Blazor WebAssembly needs a current Edge/Chrome/Firefox/Safari).
  2. Update the host webview/WebView2 to a version that includes WebAssembly.
  3. If you must support WASM-less clients, detect it and serve a static/SSR fallback instead of starting the WASM app.
  4. Confirm `WebAssembly` is present in the failing environment via a console check before reporting.

Example fix

// before
Blazor.start(); // throws 'This browser does not support WebAssembly.'

// after
if (typeof WebAssembly === 'undefined' || !WebAssembly.validate) {
  showBrowserUpgradeNotice();
} else {
  await Blazor.start();
}
Defensive patterns

Strategy: fallback

Validate before calling

function supportsWasm(): boolean {
  return typeof WebAssembly !== 'undefined' && !!WebAssembly.validate;
}

Type guard

function browserSupportsWasm(): boolean {
  return typeof WebAssembly === 'object' && typeof WebAssembly.validate === 'function';
}

Try / catch

try { await Blazor.start(); }
catch (e) { if (/does not support WebAssembly/.test(e.message)) { showUpgradeNotice(); return; } throw e; }

Prevention

When it happens

Trigger: Starting a Blazor WebAssembly app in a browser/engine without the `WebAssembly` global or where `WebAssembly.validate` is missing — older browsers (pre-2017), some embedded webviews, locked-down environments, or non-browser JS hosts (Node without a WASM polyfill).

Common situations: Targeting legacy browsers the app doesn't support; an in-app webview (older Cordova/Capacitor/UWP) with WASM disabled; bot/crawler or SSR-only fetch hitting the boot path; corporate policy stripping `WebAssembly`; testing under a headless runner that lacks WASM.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/40dabec704ec79bb. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts:124

    assertHeapIsNotLocked();
    currentHeapLock = MonoHeapLock.create();
    return currentHeapLock;
  },

  invokeWhenHeapUnlocked: function invokeWhenHeapUnlocked(callback) {
    // This is somewhat like a sync context. If we're not locked, just pass through the call directly.
    if (!currentHeapLock) {
      callback();
    } else {
      currentHeapLock.enqueuePostReleaseAction(callback);
    }
  },
};

async function importDotnetJs(startOptions: Partial<WebAssemblyStartOptions>): Promise<ModuleAPI> {
  const browserSupportsNativeWebAssembly = typeof WebAssembly !== 'undefined' && WebAssembly.validate;
  if (!browserSupportsNativeWebAssembly) {
    throw new Error('This browser does not support WebAssembly.');
  }


  // Allow overriding the URI from which the dotnet.*.js file is loaded
  if (startOptions.loadBootResource) {
    const resourceType: WebAssemblyBootResourceType = 'dotnetjs';
    const customSrc = startOptions.loadBootResource(resourceType, 'dotnet.js', '_framework/dotnet.js', '', 'js-module-dotnet');
    if (typeof (customSrc) === 'string') {
      const absoluteSrc = (new URL(customSrc, document.baseURI)).toString();
      return await import(/* webpackIgnore: true */ absoluteSrc);
    } else if (customSrc) {
      // Since we must load this via a import, it's only valid to supply a URI (and not a Request, say)
      throw new Error(`For a ${resourceType} resource, custom loaders must supply a URI string.`);
    }
  }

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore: This dynamic import is handled at runtime and does not need a type declaration.

View on GitHub (pinned to 3600ca084e)