{"record":{"id":"387ebf91bd374f2d","repo":"dotnet/aspnetcore","slug":"blazor-webassembly-has-already-started","errorCode":null,"errorMessage":"Blazor WebAssembly has already started.","messagePattern":"Blazor WebAssembly has already started\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Boot.WebAssembly.Common.ts","lineNumber":75,"sourceCode":"}\n\nexport function setWebAssemblyOptions(initializersReady: Promise<Partial<WebAssemblyStartOptions>>) {\n  if (options) {\n    throw new Error('WebAssembly options have already been configured.');\n  }\n  setOptions(initializersReady);\n\n\n  async function setOptions(initializers: Promise<Partial<WebAssemblyStartOptions>>) {\n    const configuredOptions = await initializers;\n    options = configuredOptions;\n    resolveInitializersPromise();\n  }\n}\n\nexport function startWebAssembly(components: RootComponentManager<WebAssemblyComponentDescriptor>, options: WebAssemblyServerOptions | undefined): Promise<void> {\n  if (startPromise !== undefined) {\n    throw new Error('Blazor WebAssembly has already started.');\n  }\n\n  startPromise = new Promise(startCore.bind(null, components, options));\n\n  return startPromise;\n}\n\nasync function startCore(components: RootComponentManager<WebAssemblyComponentDescriptor>, options: WebAssemblyServerOptions | undefined, resolve, _) {\n  if (inAuthRedirectIframe()) {\n    // eslint-disable-next-line @typescript-eslint/no-empty-function\n    await new Promise(() => { }); // See inAuthRedirectIframe for explanation\n  }\n\n  const platformLoadPromise = loadWebAssemblyPlatformIfNotStarted(options);\n\n  addDispatchEventMiddleware((browserRendererId, eventHandlerId, continuation) => {\n    // It's extremely unusual, but an event can be raised while we're in the middle of synchronously applying a\n    // renderbatch. For example, a renderbatch might mutate the DOM in such a way as to cause an <input> to lose","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/Boot.WebAssembly.Common.ts#L57-L93","documentation":"Thrown by startWebAssembly in Boot.WebAssembly.Common when the module-level startPromise is already defined. startWebAssembly runs the WebAssembly startup core (loading the Mono platform, root components, and entry point) and is intended to run exactly once; a second call would re-load the runtime and re-fire initializers.","triggerScenarios":"Calling the WebAssembly boot path twice per page, either via two Blazor.start() invocations or via framework re-entry.","commonSituations":"Autostart plus manual start; an error-recovery routine that calls start again after a partial success; HMR re-evaluating Boot.WebAssembly.Common; duplicate script tags.","solutions":["Call Blazor.start() once; disable autostart if you start manually.","Guard the call site with a memoized promise.","Investigate bundler/HMR configuration if the boot module is being evaluated multiple times.","Ensure the host page includes the boot script exactly once."],"exampleFix":"// before\nwindow.addEventListener('online', () => Blazor.start()); // fires after autostart\n\n// after — single guarded entry\nlet startP;\nfunction startOnce(){ return startP ?? (startP = Blazor.start()); }","handlingStrategy":"validation","validationCode":"// Guard startWebAssembly entry so startPromise is created once.\nlet startPromise;\nfunction ensureWasmStarted() {\n  return startPromise ?? (startPromise = Blazor.start());\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Blazor.start();\n} catch (e) {\n  if (/already started/.test(e.message)) return;\n  throw e;\n}","preventionTips":["Boot WebAssembly once per page.","Disable autostart when starting manually.","Investigate duplicate script inclusions.","Recover from partial-start errors by reloading the page rather than re-booting."],"tags":["blazor-webassembly","boot","lifecycle","double-start"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}