dotnet/aspnetcore · error · InvalidOperationException

State already initialized.

Error message

State already initialized.

What it means

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.

Solutions

  1. Call RestoreStateAsync(store) at most once per manager lifetime; for subsequent state refreshes use RestoreStateAsync(store, RestoreContext.ValueUpdate).
  2. Ensure each store or middleware layer restores exactly once; if multiple stores participate, route updates through the ValueUpdate context rather than re-initializing.
  3. If you need a fresh full restore, construct a new ComponentStatePersistenceManager instead of reusing the initialized one.

Example fix

// before: double restore with default context
await manager.RestoreStateAsync(store);
await manager.RestoreStateAsync(store); // throws

// after: use ValueUpdate for subsequent restores
await manager.RestoreStateAsync(store);
await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);
Defensive patterns

Strategy: validation

Validate before calling

// Track restore state in your host to avoid double-initialization.
if (!_restoreDone)
{
    await manager.RestoreStateAsync(store);
    _restoreDone = true;
}
else
{
    // subsequent refreshes must use ValueUpdate
    await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs:78

    {
        await RestoreStateAsync(store, RestoreContext.InitialValue);
    }

    /// <summary>
    /// Restores the application state.
    /// </summary>
    /// <param name="store"> The <see cref="IPersistentComponentStateStore"/> to restore the application state from.</param>
    /// <param name="context">The <see cref="RestoreContext"/> that provides additional context for the restoration.</param>
    /// <returns>A <see cref="Task"/> that will complete when the state has been restored.</returns>
    public async Task RestoreStateAsync(IPersistentComponentStateStore store, RestoreContext context)
    {
        var data = await store.GetPersistedStateAsync();

        if (_stateIsInitialized)
        {
            if (context != RestoreContext.ValueUpdate)
            {
                throw new InvalidOperationException("State already initialized.");
            }
            State.UpdateExistingState(data, context);
            foreach (var registration in _registeredRestoringCallbacks)
            {
                registration.Callback();
            }
        }
        else
        {
            State.InitializeExistingState(data, context);
            _servicesRegistry?.RegisterForPersistence(State);
            _stateIsInitialized = true;
        }
    }

    /// <summary>
    /// Persists the component application state into the given <see cref="IPersistentComponentStateStore"/>.
    /// </summary>

View on GitHub (pinned to 3600ca084e)