{"record":{"id":"7cf41cd1366bbd8b","repo":"dotnet/aspnetcore","slug":"circuit-state-this-statename-is-already-in-pro","errorCode":null,"errorMessage":"Circuit state ${this._stateName} is already in progress","messagePattern":"Circuit state (.+?) is already in progress","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts","lineNumber":687,"sourceCode":"  public constructor(\n    private _stateName: string,\n    _initialValue?: T,\n    private _resetValue?: T\n  ) {\n    this._lastValue = _initialValue;\n  }\n\n  private _promise?: Promise<T>;\n\n  private _resolve?: (value: T | PromiseLike<T>) => void;\n\n  private _reject?: (reason: any) => void;\n\n  private _lastValue?: T;\n\n  public reset(): void {\n    if (this._promise) {\n      throw new Error(`Circuit state ${this._stateName} is already in progress`);\n    }\n\n    const { promise, resolve, reject } = Promise.withResolvers<T>();\n    this._promise = promise;\n    this._resolve = resolve;\n    this._reject = reject;\n    this._lastValue = this._resetValue;\n  }\n\n  public complete(value: T): void {\n    if (!this._resolve) {\n      throw new Error(`Circuit state ${this._stateName} not initialized`);\n    }\n\n    const resolve = this._resolve;\n    this._lastValue = value;\n\n    this._promise = undefined;","sourceCodeStart":669,"sourceCodeEnd":705,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts#L669-L705","documentation":"`CircuitState.reset()` begins a new async operation (pause/resume/disconnect) by creating a fresh promise via `Promise.withResolvers`. It refuses if `_promise` already exists, because each state machine allows only one in-flight operation at a time — overlapping resets would lose track of resolvers. The thrown message names the state for diagnosis.","triggerScenarios":"Calling `reset()` on a `CircuitState` (pausing/resuming/disconnecting) while a previous operation started by an earlier `reset()` has not yet completed or failed.","commonSituations":"Two concurrent `pause()` calls; a reconnect triggered while a disconnect is mid-flight; user rapidly toggling states (pause/resume) faster than the server responds; a reconnection handler racing with an explicit disconnect.","solutions":["Before starting a new operation, await the existing one via `currentProgress()` or check `isInprogress()`.","Serialize pause/resume/disconnect through a single queue in your orchestration code so resets never overlap.","Debounce rapid user actions that map to circuit state changes.","Use the framework-provided `pauseCircuit`/`resume`/`disconnect` entry points which already check progress, rather than driving `reset()` indirectly through re-entrant calls."],"exampleFix":"// before\nasync function toggle(cm: CircuitManager) {\n  await cm.pause();   // user clicks again before pause settles\n  await cm.pause();   // second reset -> throw\n}\n\n// after\nasync function toggle(cm: CircuitManager) {\n  await cm.pause();\n  await cm.resume();  // sequence, never overlap\n}","handlingStrategy":"validation","validationCode":"function safeReset<T>(s: { isInprogress(): boolean; reset(): void }) {\n  if (s.isInprogress()) throw new Error('operation already in progress');\n  s.reset();\n}","typeGuard":null,"tryCatchPattern":"try { state.reset(); }\ncatch (e) { if (/already in progress/.test(e.message)) { await state.currentProgress(); return; } throw e; }","preventionTips":["Await the in-flight operation (currentProgress()) before resetting.","Serialize pause/resume/disconnect through a single queue.","Debounce rapid user-driven state changes.","Use the framework entry points that already check progress."],"tags":["circuit","state-machine","lifecycle","concurrency","blazor-server"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}