dotnet/aspnetcore · error · ArgumentException
There is already a persisted object under the same key '{key
Error message
There is already a persisted object under the same key '{key}' What it means
PersistAsJson throws ArgumentException when _currentState.TryAdd(key, ...) returns false, i.e. a value already exists under the same key. PersistentComponentState does not overwrite, so duplicate keys during one persist cycle are treated as a programming error.
Source
Thrown at src/Components/Components/src/PersistentComponentState.cs:120
/// <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.");
}
if (!_currentState.TryAdd(key, JsonSerializer.SerializeToUtf8Bytes(instance, type, JsonSerializerOptionsProvider.Options)))
{
throw new ArgumentException($"There is already a persisted object under the same key '{key}'");
}
}View on GitHub (pinned to 294cab2f9b)
Solutions
- Use a unique key per component/service (prefix with the component name or a GUID).
- Track which keys have been persisted and skip duplicates, or only persist from a single owner.
- If overwriting is desired, design your own state bag instead of relying on PersistAsJson.
Example fix
// before
State.PersistAsJson("state", a);
State.PersistAsJson("state", b); // duplicate -> throws
// after
State.PersistAsJson("componentA.state", a);
State.PersistAsJson("componentB.state", b); Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<string> _persistedKeys = new();
void PersistUnique(string key, object value)
{
if (!_persistedKeys.Add(key)) return; // or throw/log
State.PersistAsJson(key, value);
} Try / catch
try { State.PersistAsJson(key, value); }
catch (ArgumentException ex) when (ex.Message.Contains("already a persisted object"))
{ logger.LogWarning(ex, "Duplicate persist key {Key}", key); } Prevention
- Namespace keys per component (e.g. "MyComponent.cart").
- Track persisted keys to avoid collisions.
- Designate a single owner for each persisted key.
When it happens
Trigger: Two components or services persisting under the same key in the same cycle; calling PersistAsJson twice with the same key; key naming collisions across feature modules.
Common situations: Generic key names like "state" or "data" reused across components; multiple instances of the same component persisting; copy-paste of persistence code without unique keys.
Related errors
- The options parameter is required.
- The custom event '${eventName}' cannot have the same name as
- initialParameters must be an object, even if empty.
- descriptor must be defined when using a descriptor.
- sequence must be defined when using a descriptor.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/4723e02a9df0abb3.
Report an issue: GitHub.