dotnet/aspnetcore · critical · Error

Failed to start platform. Reason

Error message

Failed to start platform. Reason: ${ex}

What it means

Thrown in startCore (Boot.WebAssembly.Common) when either platformLoadPromise (downloading/booting the Mono WebAssembly runtime) or platform.start() rejects. The inner exception is captured and re-wrapped to make the failure point explicit. This is a fatal error: the .NET runtime did not come up, so no entry point or initializer can run.

Solutions

  1. Open the browser DevTools Network tab and inspect the failed request referenced by 'ex' — look for 404, MIME, or compression errors.
  2. Verify blazor.boot.json and all listed .wasm/.dll files are present and served with correct MIME types (application/wasm for .wasm).
  3. Clear browser cache / disable aggressive CDN caching to drop a stale boot manifest.
  4. Confirm Content-Security-Policy allows WebAssembly (add 'wasm-unsafe-eval' to script-src).
  5. Match the runtime and framework versions: republish and redeploy the entire app together.
  6. Read the full inner exception ('ex') for the specific platform error before retrying.

Example fix

// before
<script src="_framework/blazor.webassembly.js" autostart="true"></script>
<!-- publish output is missing dotnet.runtime.wasm -> platform.start() rejects -->

// after — ensure correct MIME + caching headers in server config (example: static files)
app.UseStaticFiles(new StaticFileOptions {
  ServeUnknownFileTypes = true,
  DefaultContentType = "application/wasm"
});
// and CSP: script-src 'self' 'wasm-unsafe-eval';
Defensive patterns

Strategy: try-catch

Validate before calling

// Preflight runtime assets before start.
async function preflightWasmAssets() {
  const manifest = await (await fetch('_framework/blazor.boot.json')).json();
  for (const res of Object.values(manifest.resources.runtime)) {
    // existence checks; MIME handled by server
  }
}

Try / catch

try {
  await Blazor.start();
} catch (e) {
  if (/Failed to start platform/.test(e.message)) {
    console.error('Platform start failed:', e);
    // surface inner reason, check CSP, network, MIME; do not blindly retry
    showFatalError(e);
  } else throw e;
}

Prevention

When it happens

Trigger: Mono runtime files (dotnet.*.wasm, *.dll, blazor.boot.json) fail to download, are the wrong version, are corrupt, or are served with the wrong MIME type; the browser blocks WebAssembly features (e.g. CSP, legacy browser, hardware disabled); a JS initializer throws during platform setup; mismatched runtime and framework versions.

Common situations: Stale cached blazor.boot.json after redeployment; CDN or origin returning 404/HTML for .wasm files; strict Content-Security-Policy without 'wasm-unsafe-eval'; incompatible browser; mismatched .NET runtime version between publish output and server; broken HTTP compression of .br/.gz assets.

Related errors


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

Appendix: source

Thrown at src/Components/Web.JS/src/Boot.WebAssembly.Common.ts:187

  };

  Blazor._internal.endUpdateRootComponents = (batchId: number) =>
    components.onAfterUpdateRootComponents?.(batchId);

  Blazor._internal.attachRootComponentToElement = (selector, componentId, rendererId) => {
    const element = componentAttacher.resolveRegisteredElement(selector);
    if (!element) {
      attachRootComponentToElement(selector, componentId, rendererId);
    } else {
      attachRootComponentToLogicalElement(rendererId, element, componentId, false);
    }
  };

  try {
    await platformLoadPromise;
    await platform.start();
  } catch (ex) {
    throw new Error(`Failed to start platform. Reason: ${ex}`);
  }

  // Start up the application
  platform.callEntryPoint();
  // At this point .NET has been initialized (and has yielded), we can't await the promise because it will
  // only end when the app finishes running
  const initializer = getInitializer();
  initializer.invokeAfterStartedCallbacks(Blazor);
  started = true;
  resolve();
}

export function hasStartedWebAssembly(): boolean {
  return startPromise !== undefined;
}

export function waitForBootConfigLoaded(): Promise<MonoConfig> {
  return bootConfigPromise;

View on GitHub (pinned to 3600ca084e)