dotnet/aspnetcore · error · Error
Circuit state ${this._stateName} not initialized
Error message
Circuit state ${this._stateName} not initialized What it means
`CircuitState.complete(value)` resolves the in-flight operation's promise. It throws if `_resolve` is undefined, i.e. no operation was started with `reset()` (or the prior operation already completed/failed and cleared the resolvers). Calling `complete` on an uninitialized state would resolve a non-existent promise, so it fails fast.
Source
Thrown at src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts:699
private _reject?: (reason: any) => void;
private _lastValue?: T;
public reset(): void {
if (this._promise) {
throw new Error(`Circuit state ${this._stateName} is already in progress`);
}
const { promise, resolve, reject } = Promise.withResolvers<T>();
this._promise = promise;
this._resolve = resolve;
this._reject = reject;
this._lastValue = this._resetValue;
}
public complete(value: T): void {
if (!this._resolve) {
throw new Error(`Circuit state ${this._stateName} not initialized`);
}
const resolve = this._resolve;
this._lastValue = value;
this._promise = undefined;
this._resolve = undefined;
this._reject = undefined;
resolve(value);
}
public fail(reason: any): void {
if (!this._reject) {
throw new Error(`Circuit state ${this._stateName} not initialized`);
}
const reject = this._reject;View on GitHub (pinned to 3600ca084e)
Solutions
- Always pair `reset()` with exactly one terminal call (`complete` or `fail`); guard terminal calls with `isInprogress()`.
- Ensure error and success paths cannot both run — use try/catch/finally that resolves the state once.
- Add `if (state.isInprogress()) state.complete(...)` around server-driven completions to tolerate out-of-order messages.
- Trace which SignalR handler invoked `complete` to find the duplicated/out-of-order settlement.
Example fix
// before
this._pausingState.complete(true); // throws if not in progress
// after
if (this._pausingState.isInprogress()) {
this._pausingState.complete(true);
} Defensive patterns
Strategy: validation
Validate before calling
function safeComplete<T>(s: { isInprogress(): boolean; complete(v: T): void }, v: T) {
if (s.isInprogress()) s.complete(v);
} Try / catch
try { state.complete(value); }
catch (e) { if (/not initialized/.test(e.message)) { /* already settled - ignore */ return; } throw e; } Prevention
- Pair reset() with exactly one terminal call.
- Guard completions with isInprogress().
- Make success and error paths mutually exclusive.
- Tolerate out-of-order server messages with an isInprogress check.
When it happens
Trigger: `complete()` is called on a `CircuitState` whose `reset()` was never called, or was already completed/failed (which clears `_resolve`).
Common situations: A server callback (`JS.RenderBatch`/`JS.RequestPause` completion) firing for a state that was never started or already settled; a logic bug double-completing a pause/resume; an error path that already called `fail()` then a success path calls `complete()`.
Related errors
- Circuit state ${this._stateName} is already in progress
- Circuit state ${this._stateName} is not in progress
- Circuit state ${this._stateName} is in progress
- Cannot start the circuit until Blazor Server has started.
- Cannot start a disposed circuit.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/dc2085a3e1f0052d.
Report an issue: GitHub.