{"record":{"id":"5dfac554fb55d9f0","repo":"dotnet/aspnetcore","slug":"registering-a-callback-while-persisting-state-is-n","errorCode":null,"errorMessage":"Registering a callback while persisting state is not allowed.","messagePattern":"Registering a callback while persisting state is not allowed\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/PersistentComponentState.cs","lineNumber":68,"sourceCode":"    /// <param name=\"callback\">The callback to invoke when the application is being paused.</param>\n    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>\n    public PersistingComponentStateSubscription RegisterOnPersisting(Func<Task> callback)\n        => RegisterOnPersisting(callback, null);\n\n    /// <summary>\n    /// Register a callback to persist the component state when the application is about to be paused.\n    /// Registered callbacks can use this opportunity to persist their state so that it can be retrieved when the application resumes.\n    /// </summary>\n    /// <param name=\"callback\">The callback to invoke when the application is being paused.</param>\n    /// <param name=\"renderMode\"></param>\n    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>\n    public PersistingComponentStateSubscription RegisterOnPersisting(Func<Task> callback, IComponentRenderMode? renderMode)\n    {\n        ArgumentNullException.ThrowIfNull(callback);\n\n        if (PersistingState)\n        {\n            throw new InvalidOperationException(\"Registering a callback while persisting state is not allowed.\");\n        }\n\n        var persistenceCallback = new PersistComponentStateRegistration(callback, renderMode);\n\n        _registeredCallbacks.Add(persistenceCallback);\n\n        return new PersistingComponentStateSubscription(_registeredCallbacks, persistenceCallback);\n    }\n\n    /// <summary>\n    /// Register a callback to restore the state when the application state is being restored.\n    /// </summary>\n    /// <param name=\"callback\"> The callback to invoke when the application state is being restored.</param>\n    /// <param name=\"options\">Options that control the restoration behavior.</param>\n    /// <returns>A subscription that can be used to unregister the callback when disposed.</returns>\n    public RestoringComponentStateSubscription RegisterOnRestoring(Action callback, RestoreOptions options)\n    {\n        Debug.Assert(CurrentContext != null);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/PersistentComponentState.cs#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Register persist callbacks during normal component initialization (OnInitialized/OnInitializedAsync), not from inside another persist callback.","If a callback depends on dynamically discovered state, register a single stable callback early and resolve the state inside it.","Avoid rendering new components during the persistence phase; defer their creation until after persistence completes.","In a custom host, finish all registrations before setting PersistingState = true."],"exampleFix":"// before: register lazily inside another persist callback\nstate.RegisterOnPersisting(async () =>\n{\n    state.RegisterOnPersisting(PersistExtra); // throws\n    await PersistMain();\n});\n\n// after: register both up front in OnInitialized\npublic class MyComponent : ComponentBase\n{\n    [Inject] PersistentComponentState State { get; set; } = default!;\n    protected override void OnInitialized()\n    {\n        State.RegisterOnPersisting(PersistMain);\n        State.RegisterOnPersisting(PersistExtra);\n    }\n}","handlingStrategy":"validation","validationCode":"if (state.PersistingState) throw new InvalidOperationException(\"Cannot register now; persist phase is running.\");\nstate.RegisterOnPersisting(callback);","typeGuard":null,"tryCatchPattern":"try { sub = state.RegisterOnPersisting(callback); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"while persisting state is not allowed\"))\n{ /* defer registration to the next init cycle */ }","preventionTips":["Register all persist callbacks during OnInitializedAsync, before persistence starts.","Do not render new components during the persistence phase.","In a custom host, close registration before setting PersistingState = true."],"tags":["blazor","state","persistence","lifecycle"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}