dotnet/aspnetcore · critical · Error

Failed to start platform. Reason: ${ex}

Error message

Failed to start platform. Reason: ${ex}

What it means

Thrown by startCore when either the Mono WebAssembly platform failed to load (loadWebAssemblyPlatformIfNotStarted) or platform.start() rejected. The original exception is wrapped and re-thrown so the underlying cause (download failure, runtime panic, out-of-memory, incompatible browser) is preserved in the message.

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 294cab2f9b)

Solutions

  1. Read the wrapped ${ex} in the message to identify the root cause (network status, CSP, runtime error) and address that first.
  2. Verify _framework/blazor.boot.json and all referenced .dll/.wasm files are deployed and reachable (check Network tab for 404/failure).
  3. Loosen Content-Security-Policy to allow 'wasm-unsafe-eval' (and the script/wasm sources) for the app origin.
  4. Clear browser cache / service-worker cache to remove stale build artifacts after a redeploy.
  5. If AOT/trimming is enabled, disable it or add the necessary trim-safe roots to confirm the runtime initializes.

Example fix

// before: unhandled rejection aborts the page
Blazor.start().catch(e => console.error(e));
// message: "Failed to start platform. Reason: TypeError: Failed to fetch dynamically imported module ...wasm"

// after: surface the underlying cause and retry once
try {
  await Blazor.start();
} catch (e) {
  console.error('Platform start failed:', e.message);
  const cause = e.message.replace('Failed to start platform. Reason: ', '');
  // inspect `cause`, then e.g. reload after cache-bust
  if (/Failed to fetch/.test(cause)) location.reload();
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Most root causes (network, runtime) can't be pre-validated cheaply.
// Best-effort pre-flight: probe the boot config and CSP.
async function preflightWasm() {
  const r = await fetch('_framework/blazor.boot.json', { cache: 'no-cache' });
  if (!r.ok) throw new Error('blazor.boot.json unreachable: ' + r.status);
  // CSP must allow wasm-unsafe-eval; surface a hint if missing.
  const csp = document.querySelector('meta[http-equiv="Content-Security-Policy"]')?.getAttribute('content') || '';
  if (csp && !/wasm-unsafe-eval/.test(csp)) {
    console.warn('CSP may block WebAssembly: add \'wasm-unsafe-eval\'.');
  }
}

Type guard

// Runtime support check before booting.
function browserSupportsWasm(): boolean {
  return typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function';
}

Try / catch

try {
  await Blazor.start();
} catch (e) {
  const msg = (e as Error).message;
  if (msg.startsWith('Failed to start platform.')) {
    const cause = msg.replace('Failed to start platform. Reason: ', '');
    console.error('WASM platform failed:', cause);
    if (/Failed to fetch|NetworkError|404/.test(cause)) {
      // bust stale cache and retry once
      if ('caches' in window) await caches.delete('blazor');
      location.reload();
    }
  } else throw e;
}

Prevention

When it happens

Trigger: Network failure downloading _framework/blazor.boot.json, the .wasm binary, or the .dll files; the Mono runtime throwing during initialization; a browser without WebAssembly support or with a Content-Security-Policy that blocks wasm-unsafe-eval; out-of-memory on low-end devices; AOT mismatch between published artifacts.

Common situations: Offline or flaky network during app load; aggressive CSP without 'wasm-unsafe-eval'; publishing with trimming/AOT that removes required types; cached stale build artifacts after redeploy; older mobile browsers without full WASM support.

Related errors


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