{"record":{"id":"ca6ea4a5200f0dfa","repo":"dotnet/aspnetcore","slug":"state-already-initialized","errorCode":null,"errorMessage":"State already initialized.","messagePattern":"State already initialized\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs","lineNumber":78,"sourceCode":"    {\n        await RestoreStateAsync(store, RestoreContext.InitialValue);\n    }\n\n    /// <summary>\n    /// Restores the application state.\n    /// </summary>\n    /// <param name=\"store\"> The <see cref=\"IPersistentComponentStateStore\"/> to restore the application state from.</param>\n    /// <param name=\"context\">The <see cref=\"RestoreContext\"/> that provides additional context for the restoration.</param>\n    /// <returns>A <see cref=\"Task\"/> that will complete when the state has been restored.</returns>\n    public async Task RestoreStateAsync(IPersistentComponentStateStore store, RestoreContext context)\n    {\n        var data = await store.GetPersistedStateAsync();\n\n        if (_stateIsInitialized)\n        {\n            if (context != RestoreContext.ValueUpdate)\n            {\n                throw new InvalidOperationException(\"State already initialized.\");\n            }\n            State.UpdateExistingState(data, context);\n            foreach (var registration in _registeredRestoringCallbacks)\n            {\n                registration.Callback();\n            }\n        }\n        else\n        {\n            State.InitializeExistingState(data, context);\n            _servicesRegistry?.RegisterForPersistence(State);\n            _stateIsInitialized = true;\n        }\n    }\n\n    /// <summary>\n    /// Persists the component application state into the given <see cref=\"IPersistentComponentStateStore\"/>.\n    /// </summary>","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs#L60-L96","documentation":"ComponentStatePersistenceManager.RestoreStateAsync guards the single-initialization invariant: once _stateIsInitialized is true, the only legal re-entry is with RestoreContext.ValueUpdate (which routes to State.UpdateExistingState). Any other restore context on an already-initialized manager means a second full initialization is being attempted, which would re-run service registration and double-bind restoring callbacks, so the manager throws.","triggerScenarios":"Calling RestoreStateAsync(store) (the single-argument overload, which uses RestoreContext.InitialValue) twice on the same ComponentStatePersistenceManager instance. Or calling RestoreStateAsync(store, RestoreContext.InitialValue) after a prior restore completed. The host or a custom middleware invoking restore more than once for the same request/circuit without switching to ValueUpdate.","commonSituations":"A Blazor Web App endpoint or middleware that runs prerender restore and then, due to a misconfigured pipeline, restores again for the same render. Wiring multiple IPersistentComponentStateStore providers that each call RestoreStateAsync with the default context. Custom hosting that reuses a single manager across prerender and interactive startup.","solutions":["Call RestoreStateAsync(store) at most once per manager lifetime; for subsequent state refreshes use RestoreStateAsync(store, RestoreContext.ValueUpdate).","Ensure each store or middleware layer restores exactly once; if multiple stores participate, route updates through the ValueUpdate context rather than re-initializing.","If you need a fresh full restore, construct a new ComponentStatePersistenceManager instead of reusing the initialized one."],"exampleFix":"// before: double restore with default context\nawait manager.RestoreStateAsync(store);\nawait manager.RestoreStateAsync(store); // throws\n\n// after: use ValueUpdate for subsequent restores\nawait manager.RestoreStateAsync(store);\nawait manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);","handlingStrategy":"validation","validationCode":"// Track restore state in your host to avoid double-initialization.\nif (!_restoreDone)\n{\n    await manager.RestoreStateAsync(store);\n    _restoreDone = true;\n}\nelse\n{\n    // subsequent refreshes must use ValueUpdate\n    await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call RestoreStateAsync(store) exactly once per manager; use ValueUpdate for later passes.","Centralize restore invocation in a single middleware/endpoint to prevent duplicate calls.","For tests, construct a fresh manager per restore scenario."],"tags":["blazor","persistent-state","restore","lifecycle"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}