{"record":{"id":"7cfa7eee05317713","repo":"dotnet/aspnetcore","slug":"persisting-state-is-only-allowed-during-an-onpersi","errorCode":null,"errorMessage":"Persisting state is only allowed during an OnPersisting callback.","messagePattern":"Persisting state is only allowed during an OnPersisting callback\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/PersistentComponentState.cs","lineNumber":115,"sourceCode":"        }\n\n        return default;\n    }\n\n    /// <summary>\n    /// Serializes <paramref name=\"instance\"/> as JSON and persists it under the given <paramref name=\"key\"/>.\n    /// </summary>\n    /// <typeparam name=\"TValue\">The <paramref name=\"instance\"/> type.</typeparam>\n    /// <param name=\"key\">The key to use to persist the state.</param>\n    /// <param name=\"instance\">The instance to persist.</param>\n    [RequiresUnreferencedCode(\"JSON serialization and deserialization might require types that cannot be statically analyzed.\")]\n    public void PersistAsJson<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string key, TValue instance)\n    {\n        ArgumentNullException.ThrowIfNull(key);\n\n        if (!PersistingState)\n        {\n            throw new InvalidOperationException(\"Persisting state is only allowed during an OnPersisting callback.\");\n        }\n\n        if (!_currentState.TryAdd(key, JsonSerializer.SerializeToUtf8Bytes(instance, JsonSerializerOptionsProvider.Options)))\n        {\n            throw new ArgumentException($\"There is already a persisted object under the same key '{key}'\");\n        }\n    }\n\n    [RequiresUnreferencedCode(\"JSON serialization and deserialization might require types that cannot be statically analyzed.\")]\n    internal void PersistAsJson(string key, object instance, [DynamicallyAccessedMembers(JsonSerialized)] Type type)\n    {\n        ArgumentNullException.ThrowIfNull(key);\n\n        if (!PersistingState)\n        {\n            throw new InvalidOperationException(\"Persisting state is only allowed during an OnPersisting callback.\");\n        }\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/PersistentComponentState.cs#L97-L133","documentation":"PersistAsJson<T> (public generic) throws InvalidOperationException when PersistingState is false. State may only be written during an OnPersisting callback, which the framework gates by setting PersistingState=true; calling PersistAsJson from arbitrary code is rejected.","triggerScenarios":"Calling State.PersistAsJson(...) from OnInitialized, OnAfterRender, an event handler, or any non-persisting context; calling it after the persist phase has ended.","commonSituations":"Developers assuming state can be persisted at any time; refactoring persistence logic out of the OnPersisting callback; timing issues where the callback registration did not run.","solutions":["Move the PersistAsJson call inside a method registered via RegisterOnPersisting (the OnPersisting callback).","Verify the subscription is created in OnInitialized so the callback actually runs.","Do not call PersistAsJson from constructors, render, or event handlers."],"exampleFix":"// before\nprotected override void OnInitialized()\n{\n    State.PersistAsJson(\"cart\", _cart); // outside persist phase -> throws\n}\n\n// after\nprotected override void OnInitialized()\n{\n    State.RegisterOnPersisting(() => { State.PersistAsJson(\"cart\", _cart); return Task.CompletedTask; });\n}","handlingStrategy":"validation","validationCode":"protected override void OnInitialized()\n{\n    State.RegisterOnPersisting(Persist);\n}\nprivate Task Persist()\n{\n    // PersistingState is true here; safe to persist\n    State.PersistAsJson(\"app.state\", _data);\n    return Task.CompletedTask;\n}","typeGuard":null,"tryCatchPattern":"try { State.PersistAsJson(key, value); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"only allowed during an OnPersisting callback\"))\n{ logger.LogError(ex, \"PersistAsJson called outside persist phase\"); }","preventionTips":["Only call PersistAsJson from within an OnPersisting callback.","Verify the callback registration happened in OnInitialized.","Avoid persisting from event handlers or render methods."],"tags":["blazor","persistent-state","lifecycle","serialization"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}