dotnet/aspnetcore · error · Error

Circuit options have already been configured.

Error message

Circuit options have already been configured.

What it means

Thrown by setCircuitOptions in Boot.Server.Common when the module-level 'options' variable is already set. setCircuitOptions is intended to run exactly once per Blazor Server boot; calling it again means the boot path executed twice, which would overwrite resolved CircuitStartOptions and leave the circuit in an inconsistent state.

Solutions

  1. Ensure Blazor.start() is called at most once per page load; remove duplicate invocation sites.
  2. If you are unsure whether Blazor has started, guard with a flag or check Blazor's documented started state before calling start.
  3. Disable autostart and call start exactly once yourself when you need explicit control.
  4. Audit bundler/SVG-inlined script setup so the boot module is not imported twice.

Example fix

// before — autostart plus a manual call
<script autostart="true" src="blazor.web.js"></script>
<script>Blazor.start({ ... });</script> // double start

// after — disable autostart and start once
<script src="blazor.web.js" autostart="false"></script>
<script>Blazor.start({ ... });</script>
Defensive patterns

Strategy: validation

Validate before calling

// Guard the start call so setCircuitOptions is invoked once.
let bootPromise;
function ensureBlazorServerStarted(opts) {
  return bootPromise ?? (bootPromise = Blazor.start(opts));
}

Try / catch

try {
  await Blazor.start(opts);
} catch (e) {
  if (/already been configured|already started/.test(e.message)) {
    // already booted — treat as success
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking Blazor.start() (or the Boot.Server boot() entrypoint) more than once in the same page, or manually calling setCircuitOptions after the framework already did so. The second call hits the populated 'options' guard.

Common situations: A script tag calling Blazor.start() in addition to the auto-start logic; a SPA shell that re-initializes Blazor on navigation; bundler misconfiguration causing the boot module to be evaluated twice; mixing manual and automatic startup.

Related errors


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

Appendix: source

Thrown at src/Components/Web.JS/src/Boot.Server.Common.ts:27

import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
import { discoverServerPersistedState, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
import { JSEventRegistry } from './Services/JSEventRegistry';
import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.Server';
import { RootComponentManager } from './Services/RootComponentManager';
import { WebRendererId } from './Rendering/WebRendererId';
import { addDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods';

let initializersPromise: Promise<void> | undefined;
let appState: string;
let circuit: CircuitManager;
let options: CircuitStartOptions;
let logger: ConsoleLogger;
let serverStartPromise: Promise<void>;
let circuitStarting: Promise<boolean> | undefined;

export function setCircuitOptions(initializersReady: Promise<Partial<CircuitStartOptions>>) {
  if (options) {
    throw new Error('Circuit options have already been configured.');
  }

  initializersPromise = setOptions(initializersReady);

  async function setOptions(initializers: Promise<Partial<CircuitStartOptions>>): Promise<void> {
    const configuredOptions = await initializers;
    options = resolveOptions(configuredOptions);
  }
}

export function startServer(components: RootComponentManager<ServerComponentDescriptor>, jsEventRegistry: JSEventRegistry): Promise<void> {
  if (serverStartPromise !== undefined) {
    throw new Error('Blazor Server has already started.');
  }

  serverStartPromise = new Promise(startServerCore.bind(null, components, jsEventRegistry));

  return serverStartPromise;

View on GitHub (pinned to 3600ca084e)