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
- Require a modern, WASM-capable browser and communicate that to users (Blazor WebAssembly needs a current Edge/Chrome/Firefox/Safari).
- Update the host webview/WebView2 to a version that includes WebAssembly.
- If you must support WASM-less clients, detect it and serve a static/SSR fallback instead of starting the WASM app.
- 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
- Detect WebAssembly support before starting and show an upgrade notice.
- Target only WASM-capable browsers in your support matrix.
- Keep host webviews (WebView2) updated.
- Serve a static/SSR fallback for unsupported clients.
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
- The runtime must be loaded before it gets configured.
- For a resource, custom loaders must supply a URI string.
- assembly must be defined when using a descriptor.
- Could not find any element matching selector
- could not find global
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)