dotnet/aspnetcore · error · InvalidOperationException
Persisting state is only allowed during an OnPersisting…
Error message
Persisting state is only allowed during an OnPersisting callback.
What it means
Thrown by the public PersistAsJson<T> when PersistingState is false. PersistentComponentState only allows writing during the OnPersisting phase so that persisted data is consistent and captured before the application is paused. Calling PersistAsJson outside that window would write data the host will never serialize or transmit.
Solutions
- Move the PersistAsJson call inside a callback registered via RegisterOnPersisting.
- Capture the data you need into a field during normal execution, then read that field inside the OnPersisting callback to persist it.
- Do not expose PersistentComponentState to code that runs outside the persist phase (e.g. a long-running service).
- If you need persistence outside the framework cycle, use your own storage; PersistentComponentState is lifecycle-bound.
Example fix
// before: called from an event handler - outside the persist phase
private void OnSave() => state.PersistAsJson("profile", _profile); // throws
// after: stash the value and persist it from the registered callback
private UserProfile _profile = new();
protected override void OnInitialized()
=> state.RegisterOnPersisting(() => { state.PersistAsJson("profile", _profile); return Task.CompletedTask; });
private void OnSave() => _profile = ComputeProfile(); Defensive patterns
Strategy: validation
Validate before calling
if (!state.PersistingState) throw new InvalidOperationException("PersistAsJson must run inside an OnPersisting callback."); Try / catch
try { state.PersistAsJson(key, instance); }
catch (InvalidOperationException ex) when (ex.Message.Contains("only allowed during an OnPersisting callback"))
{ /* move the call inside a RegisterOnPersisting callback */ } Prevention
- Register a persist callback once in OnInitialized and write all state from it.
- Capture the live data in a field; read the field inside the callback.
- Do not expose PersistentComponentState to code outside the component lifecycle.
When it happens
Trigger: Invoking state.PersistAsJson(key, instance) from OnInitializedAsync, a button click handler, OnParametersSet, or any code path outside an OnPersisting-registered callback. The PersistingState flag is only true while the framework is running the persist callbacks.
Common situations: Persisting on demand from an event handler instead of from a registered callback; misunderstanding the lifecycle and assuming PersistAsJson can be called any time; refactoring that moved a PersistAsJson call out of a callback.
Related errors
- PersistentComponentState already initialized.
- Registering a callback while persisting state is not…
- existingState
- State already persisted.
- There is already a persisted object under the same key
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/7cfa7eee05317713.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Components/src/PersistentComponentState.cs:115
}
return default;
}
/// <summary>
/// Serializes <paramref name="instance"/> as JSON and persists it under the given <paramref name="key"/>.
/// </summary>
/// <typeparam name="TValue">The <paramref name="instance"/> type.</typeparam>
/// <param name="key">The key to use to persist the state.</param>
/// <param name="instance">The instance to persist.</param>
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
public void PersistAsJson<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string key, TValue instance)
{
ArgumentNullException.ThrowIfNull(key);
if (!PersistingState)
{
throw new InvalidOperationException("Persisting state is only allowed during an OnPersisting callback.");
}
if (!_currentState.TryAdd(key, JsonSerializer.SerializeToUtf8Bytes(instance, JsonSerializerOptionsProvider.Options)))
{
throw new ArgumentException($"There is already a persisted object under the same key '{key}'");
}
}
[RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
internal void PersistAsJson(string key, object instance, [DynamicallyAccessedMembers(JsonSerialized)] Type type)
{
ArgumentNullException.ThrowIfNull(key);
if (!PersistingState)
{
throw new InvalidOperationException("Persisting state is only allowed during an OnPersisting callback.");
}
View on GitHub (pinned to 3600ca084e)