OrchardCMS/OrchardCore · error · OpenIddictExceptions.ConcurrencyException
The application was concurrently updated and cannot be…
Error message
The application was concurrently updated and cannot be persisted in its current state. Reload the application from the database and retry the operation.
What it means
OpenIdApplicationStore.UpdateAsync saves the OpenIddict application document via YesSql. YesSql detects a version conflict (ConcurrencyException) when another operation updated the same document, and the store translates it into OpenIddictExceptions.ConcurrencyException, following the OpenIddict store contract.
Solutions
- Retry the operation: reload the application via FindAsync and re-apply the update, as the message instructs.
- Serialize writes to the same application (locking, single writer, or queue) to avoid conflicts.
- Reduce write frequency to application documents (avoid persisting on every token flow when possible).
Example fix
// before
await store.UpdateAsync(application, cancellationToken);
// after
try
{
await store.UpdateAsync(application, cancellationToken);
}
catch (OpenIddictExceptions.ConcurrencyException)
{
application = await store.FindAsync(application.ClientId, cancellationToken);
// re-apply changes and retry once
} Defensive patterns
Strategy: retry
Try / catch
try
{
await store.UpdateAsync(app, ct);
}
catch (OpenIddictExceptions.ConcurrencyException)
{
var fresh = await store.FindAsync(app.ClientId, ct);
// re-apply changes to fresh, retry once with bounded backoff
} Prevention
- Serialize writes to the same OpenIddict application document.
- Keep a short retry-with-reload policy for optimistic concurrency conflicts.
- Avoid persisting application documents in high-frequency token flows.
- Watch for duplicate background jobs acting on the same client.
When it happens
Trigger: Two concurrent requests updating the same OpenIddict application (e.g. concurrent client edits, token refresh writing to the same application document) causing SaveChangesAsync to fail the optimistic concurrency check.
Common situations: High-concurrency OAuth/OpenID flows hitting the same client; duplicate background jobs processing the same application; users editing the same client in the admin UI from two tabs.
Related errors
- The authorization was concurrently updated and cannot be…
- The scope was concurrently updated and cannot be persisted…
- The token was concurrently updated and cannot be persisted…
- Unable to reload the tenant
- Can't resolve a scope on tenant
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/18f15eb9902bf14e.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.OpenId.Core/YesSql/Stores/OpenIdApplicationStore.cs:471
return default;
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TApplication application, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(application);
cancellationToken.ThrowIfCancellationRequested();
await _session.SaveAsync(application, checkConcurrency: true, collection: OpenIdCollection, cancellationToken: cancellationToken);
try
{
await _session.SaveChangesAsync(cancellationToken);
}
catch (ConcurrencyException exception)
{
throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder()
.AppendLine("The application was concurrently updated and cannot be persisted in its current state.")
.Append("Reload the application from the database and retry the operation.")
.ToString(), exception);
}
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetRolesAsync(TApplication application, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(application);
return ValueTask.FromResult(application.Roles);
}
/// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> ListInRoleAsync(string role, CancellationToken cancellationToken)
{
ArgumentException.ThrowIfNullOrEmpty(role);View on GitHub (pinned to 4306c0717f)