{"record":{"id":"4723e02a9df0abb3","repo":"dotnet/aspnetcore","slug":"there-is-already-a-persisted-object-under-the-same","errorCode":null,"errorMessage":"There is already a persisted object under the same key '{key}'","messagePattern":"There is already a persisted object under the same key '(.+?)'","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/PersistentComponentState.cs","lineNumber":120,"sourceCode":"    /// <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\n        if (!_currentState.TryAdd(key, JsonSerializer.SerializeToUtf8Bytes(instance, type, JsonSerializerOptionsProvider.Options)))\n        {\n            throw new ArgumentException($\"There is already a persisted object under the same key '{key}'\");\n        }\n    }","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/PersistentComponentState.cs#L102-L138","documentation":"Thrown by the public PersistAsJson<T> when _currentState.TryAdd(key, ...) returns false, i.e. the same key has already been persisted in this cycle. Keys are unique within a persist pass to avoid one component silently overwriting another's data. The duplicate is rejected so the conflict surfaces immediately.","triggerScenarios":"Two components (or two persist callbacks) both call PersistAsJson with the same key during one persist phase; a single component registers two persist callbacks that write the same key; a key constant reused across feature modules.","commonSituations":"Shared key constants (e.g. \"state\") used by multiple components; a component rendered multiple times in the same tree each registering persistence under a fixed key; refactoring that merged two persistence modules without namespacing their keys.","solutions":["Namespace keys per component or feature: use $\"{GetType().FullName}:state\" or a constant unique to the module.","Ensure only one component owns each persisted key; coordinate ownership in code review.","If multiple values are legitimately needed, combine them into one persisted object or use distinct keys.","Use TryTakeFromJson on restore with the exact same namespaced key."],"exampleFix":"// before: two components share the literal \"data\" key\nstate.PersistAsJson(\"data\", _value);\n\n// after: scope the key to the owning component\nstate.PersistAsJson($\"{GetType().FullName}:data\", _value);","handlingStrategy":"validation","validationCode":"static string ScopedKey(object owner, string key) => $\"{owner.GetType().FullName}:{key}\";\n\n// then always pass ScopedKey(this, \"data\")","typeGuard":null,"tryCatchPattern":"try { state.PersistAsJson(key, instance); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"already a persisted object under the same key\"))\n{ /* use a more specific key, or merge payloads */ }","preventionTips":["Namespace persisted keys by component or feature.","Centralize key constants and review for duplicates in code review.","Dispose the PersistingComponentStateSubscription when a component unmounts to avoid stale registrations."],"tags":["blazor","state","persistence","keys"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}