dotnet/aspnetcore · error · InvalidOperationException

Registering a callback while persisting state is not…

Error message

Registering a callback while persisting state is not allowed.

What it means

Thrown by RegisterOnPersisting when PersistingState is already true. Persist callbacks may only be registered before the persistence phase begins; once the framework starts invoking persisters, registering a new one would either miss the current cycle or re-enter it, both of which are unsafe.

Solutions

  1. Register persist callbacks during normal component initialization (OnInitialized/OnInitializedAsync), not from inside another persist callback.
  2. If a callback depends on dynamically discovered state, register a single stable callback early and resolve the state inside it.
  3. Avoid rendering new components during the persistence phase; defer their creation until after persistence completes.
  4. In a custom host, finish all registrations before setting PersistingState = true.

Example fix

// before: register lazily inside another persist callback
state.RegisterOnPersisting(async () =>
{
    state.RegisterOnPersisting(PersistExtra); // throws
    await PersistMain();
});

// after: register both up front in OnInitialized
public class MyComponent : ComponentBase
{
    [Inject] PersistentComponentState State { get; set; } = default!;
    protected override void OnInitialized()
    {
        State.RegisterOnPersisting(PersistMain);
        State.RegisterOnPersisting(PersistExtra);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if (state.PersistingState) throw new InvalidOperationException("Cannot register now; persist phase is running.");
state.RegisterOnPersisting(callback);

Try / catch

try { sub = state.RegisterOnPersisting(callback); }
catch (InvalidOperationException ex) when (ex.Message.Contains("while persisting state is not allowed"))
{ /* defer registration to the next init cycle */ }

Prevention

When it happens

Trigger: Calling PersistentComponentState.RegisterOnPersisting(...) from inside another persisting callback, or from a component whose OnInitialized runs during the persistence pass. The flag flips true while the framework enumerates and invokes registered callbacks.

Common situations: A component dynamically rendered during persist; calling RegisterOnPersisting lazily on first persist; a callback that triggers a re-render that registers another callback; misuse in custom hosting where persistence is invoked manually while still accepting registrations.

Related errors


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

Appendix: source

Thrown at src/Components/Components/src/PersistentComponentState.cs:68

    /// <param name="callback">The callback to invoke when the application is being paused.</param>
    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>
    public PersistingComponentStateSubscription RegisterOnPersisting(Func<Task> callback)
        => RegisterOnPersisting(callback, null);

    /// <summary>
    /// Register a callback to persist the component state when the application is about to be paused.
    /// Registered callbacks can use this opportunity to persist their state so that it can be retrieved when the application resumes.
    /// </summary>
    /// <param name="callback">The callback to invoke when the application is being paused.</param>
    /// <param name="renderMode"></param>
    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>
    public PersistingComponentStateSubscription RegisterOnPersisting(Func<Task> callback, IComponentRenderMode? renderMode)
    {
        ArgumentNullException.ThrowIfNull(callback);

        if (PersistingState)
        {
            throw new InvalidOperationException("Registering a callback while persisting state is not allowed.");
        }

        var persistenceCallback = new PersistComponentStateRegistration(callback, renderMode);

        _registeredCallbacks.Add(persistenceCallback);

        return new PersistingComponentStateSubscription(_registeredCallbacks, persistenceCallback);
    }

    /// <summary>
    /// Register a callback to restore the state when the application state is being restored.
    /// </summary>
    /// <param name="callback"> The callback to invoke when the application state is being restored.</param>
    /// <param name="options">Options that control the restoration behavior.</param>
    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>
    public RestoringComponentStateSubscription RegisterOnRestoring(Action callback, RestoreOptions options)
    {
        Debug.Assert(CurrentContext != null);

View on GitHub (pinned to 3600ca084e)