{"record":{"id":"18f15eb9902bf14e","repo":"OrchardCMS/OrchardCore","slug":"the-application-was-concurrently-updated-and-cannot-be","errorCode":null,"errorMessage":"The application was concurrently updated and cannot be persisted in its current state.\nReload the application from the database and retry the operation.","messagePattern":"The application was concurrently updated and cannot be persisted in its current state\\.\nReload the application from the database and retry the operation\\.","errorType":"exception","errorClass":"OpenIddictExceptions.ConcurrencyException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.OpenId.Core/YesSql/Stores/OpenIdApplicationStore.cs","lineNumber":471,"sourceCode":"        return default;\n    }\n\n    /// <inheritdoc/>\n    public virtual async ValueTask UpdateAsync(TApplication application, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(application);\n\n        cancellationToken.ThrowIfCancellationRequested();\n\n        await _session.SaveAsync(application, checkConcurrency: true, collection: OpenIdCollection, cancellationToken: cancellationToken);\n\n        try\n        {\n            await _session.SaveChangesAsync(cancellationToken);\n        }\n        catch (ConcurrencyException exception)\n        {\n            throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder()\n                .AppendLine(\"The application was concurrently updated and cannot be persisted in its current state.\")\n                .Append(\"Reload the application from the database and retry the operation.\")\n                .ToString(), exception);\n        }\n    }\n\n    /// <inheritdoc/>\n    public virtual ValueTask<ImmutableArray<string>> GetRolesAsync(TApplication application, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(application);\n\n        return ValueTask.FromResult(application.Roles);\n    }\n\n    /// <inheritdoc/>\n    public virtual IAsyncEnumerable<TApplication> ListInRoleAsync(string role, CancellationToken cancellationToken)\n    {\n        ArgumentException.ThrowIfNullOrEmpty(role);","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.OpenId.Core/YesSql/Stores/OpenIdApplicationStore.cs#L453-L489","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nawait store.UpdateAsync(application, cancellationToken);\n// after\ntry\n{\n    await store.UpdateAsync(application, cancellationToken);\n}\ncatch (OpenIddictExceptions.ConcurrencyException)\n{\n    application = await store.FindAsync(application.ClientId, cancellationToken);\n    // re-apply changes and retry once\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    await store.UpdateAsync(app, ct);\n}\ncatch (OpenIddictExceptions.ConcurrencyException)\n{\n    var fresh = await store.FindAsync(app.ClientId, ct);\n    // re-apply changes to fresh, retry once with bounded backoff\n}","preventionTips":["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."],"tags":["openid","concurrency","yessql"],"backgroundTag":"database-write-failed","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}