dotnet/aspnetcore · error · InvalidOperationException
State already initialized.
Error message
State already initialized.
What it means
Thrown by ComponentStatePersistenceManager.RestoreStateAsync when _stateIsInitialized is already true and the supplied RestoreContext is not ValueUpdate. The manager permits re-entry only for RestoreContext.ValueUpdate (which routes to State.UpdateExistingState); any other context on an already-initialized manager is treated as a misuse.
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 294cab2f9b)
Solutions
- Call the initial RestoreStateAsync exactly once per manager lifetime; gate with your own flag or rely on DI scoped/singleton semantics.
- For subsequent in-place updates pass RestoreContext.ValueUpdate explicitly.
- If a fresh restore is genuinely needed, use a new ComponentStatePersistenceManager instance (new DI scope / new circuit).
- Confirm framework integration isn't already restoring before your code does.
Example fix
// before
await manager.RestoreStateAsync(store); // called on every request -> throws 2nd time
// after
if (!_restored)
{
await manager.RestoreStateAsync(store);
_restored = true;
}
else
{
await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);
} Defensive patterns
Strategy: validation
Validate before calling
private bool _restored;
async Task RestoreOnceAsync(ComponentStatePersistenceManager manager, IPersistentComponentStateStore store)
{
if (_restored)
{
// subsequent updates must use ValueUpdate
await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);
return;
}
await manager.RestoreStateAsync(store);
_restored = true;
} Try / catch
try
{
await manager.RestoreStateAsync(store);
}
catch (InvalidOperationException ex) when (ex.Message == "State already initialized.")
{
// already restored - route through ValueUpdate instead
await manager.RestoreStateAsync(store, RestoreContext.ValueUpdate);
} Prevention
- Gate the initial restore with a flag so it runs once per manager lifetime.
- Match DI lifetime to restore lifetime (scoped per circuit).
- Use RestoreContext.ValueUpdate for any subsequent restore on the same manager.
- Audit middleware for duplicate restore invocations.
When it happens
Trigger: Calling RestoreStateAsync(store) (default context) a second time on the same ComponentStatePersistenceManager instance; middleware that restores on every request without gating on initialization.
Common situations: Custom host/middleware that wires restore per-request without a once-per-lifetime guard; a test that reuses one manager across requests; double-registration of restore middleware in the pipeline.
Related errors
- Cannot update existing state: previous state has not been cl
- State already persisted.
- The registered callback {registration.Callback.Method.Name}
- The type '{targetType.FullName}' declares a property matchin
- A public property '{propertyName}' on component type '{type.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/ca6ea4a5200f0dfa.
Report an issue: GitHub.