{"record":{"id":"e2525e2b0c61cb9a","repo":"dotnet/aspnetcore","slug":"blazor-has-already-started","errorCode":null,"errorMessage":"Blazor has already started.","messagePattern":"Blazor has already started\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Boot.Server.ts","lineNumber":19,"sourceCode":"// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\nimport { Blazor } from './GlobalExports';\nimport { shouldAutoStart } from './BootCommon';\nimport { CircuitStartOptions, resolveOptions } from './Platform/Circuits/CircuitStartOptions';\nimport { setCircuitOptions, startServer } from './Boot.Server.Common';\nimport { ServerComponentDescriptor, discoverComponents } from './Services/ComponentDescriptorDiscovery';\nimport { DotNet } from '@microsoft/dotnet-js-interop';\nimport { InitialRootComponentsList } from './Services/InitialRootComponentsList';\nimport { JSEventRegistry } from './Services/JSEventRegistry';\n\ntype BlazorServerStartOptions = Partial<CircuitStartOptions> & { circuit?: Partial<CircuitStartOptions> };\n\nlet started = false;\n\nfunction boot(userOptions?: BlazorServerStartOptions): Promise<void> {\n  if (started) {\n    throw new Error('Blazor has already started.');\n  }\n  started = true;\n\n  // Accept the `circuit` property from the blazor.web.js options format\n  const normalizedOptions = userOptions?.circuit ?? userOptions;\n  const configuredOptions = resolveOptions(normalizedOptions);\n  setCircuitOptions(Promise.resolve(configuredOptions || {}));\n\n  const serverComponents = discoverComponents(document, 'server') as ServerComponentDescriptor[];\n  const components = new InitialRootComponentsList(serverComponents);\n  return startServer(components, JSEventRegistry.create(Blazor));\n}\n\nBlazor.start = boot;\nwindow['DotNet'] = DotNet;\n\nif (shouldAutoStart()) {\n  boot();","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/Boot.Server.ts#L1-L37","documentation":"Thrown by boot() in Boot.Server.ts when the module-level 'started' flag is already true. This is the top-level guard for the Blazor Server boot entrypoint and means the application has already initialized; a second boot would double-register root components, re-attach the dispatcher, and re-run initializers.","triggerScenarios":"Calling the Server boot entrypoint (Blazor.start in a Server-configured app, or the boot function directly) more than once per page load.","commonSituations":"Autostart left enabled while a script also calls Blazor.start(); a micro-frontend or shell that re-runs boot on route change; bundler duplication evaluating Boot.Server.ts twice; a retry-on-error handler that re-invokes boot after partial success.","solutions":["Call Blazor.start() exactly once; remove duplicate invocations.","Disable autostart (autostart=\"false\") and start manually from a single place.","Memoize the boot promise at your call site so retries/re-entries return the same promise.","Audit module duplication if HMR or bundler config could re-evaluate Boot.Server."],"exampleFix":"// before\nwindow.addEventListener('load', () => Blazor.start());\n// plus autostart=true in the script tag -> second boot throws\n\n// after\n<script src=\"blazor.web.js\" autostart=\"false\"></script>\n<script>\n  window.addEventListener('load', () => Blazor.start());\n</script>","handlingStrategy":"validation","validationCode":"// Single guarded entrypoint for Server boot.\nlet started;\nfunction bootServerOnce(opts) {\n  if (started) return started;\n  started = Blazor.start(opts);\n  return started;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Blazor.start(opts);\n} catch (e) {\n  if (/already started/.test(e.message)) return;\n  throw e;\n}","preventionTips":["Use autostart OR a single manual start, never both.","Memoize the start promise at one location.","Avoid re-invoking boot from navigation handlers.","Confirm HMR/bundler is not duplicating Boot.Server.ts."],"tags":["blazor-server","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"}