{"record":{"id":"beb17857e6b6a1cc","repo":"OrchardCMS/OrchardCore","slug":"the-authorization-was-concurrently-updated-and-cannot-be","errorCode":null,"errorMessage":"The authorization was concurrently updated and cannot be persisted in its current state.\nReload the authorization from the database and retry the operation.","messagePattern":"The authorization was concurrently updated and cannot be persisted in its current state\\.\nReload the authorization from the database and retry the operation\\.","errorType":"exception","errorClass":"OpenIddictExceptions.ConcurrencyException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.OpenId.Core/YesSql/Stores/OpenIdAuthorizationStore.cs","lineNumber":573,"sourceCode":"        return default;\n    }\n\n    /// <inheritdoc/>\n    public virtual async ValueTask UpdateAsync(TAuthorization authorization, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(authorization);\n\n        cancellationToken.ThrowIfCancellationRequested();\n\n        await _session.SaveAsync(authorization, checkConcurrency: true, collection: OpenIdCollection, cancellationToken: cancellationToken);\n\n        try\n        {\n            await _session.FlushAsync(cancellationToken);\n        }\n        catch (ConcurrencyException exception)\n        {\n            throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder()\n                .AppendLine(\"The authorization was concurrently updated and cannot be persisted in its current state.\")\n                .Append(\"Reload the authorization from the database and retry the operation.\")\n                .ToString(), exception);\n        }\n    }\n}\n","sourceCodeStart":555,"sourceCodeEnd":580,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.OpenId.Core/YesSql/Stores/OpenIdAuthorizationStore.cs#L555-L580","documentation":"OpenIdAuthorizationStore.UpdateAsync flushes the session to persist an OpenIddict authorization document. A YesSql ConcurrencyException (another writer updated the same authorization) is caught and rethrown as OpenIddictExceptions.ConcurrencyException per the OpenIddict contract.","triggerScenarios":"Concurrent token/authorization flows updating the same authorization row (e.g. two refresh-token requests for the same grant, or parallel background cleanup and token redemption).","commonSituations":"Refresh-token storms from multiple devices/clients using the same authorization; duplicate scheduled tasks revoking or updating authorizations; race between logout (revocation) and token refresh.","solutions":["Reload the authorization from the database and retry the update.","Make authorization updates idempotent and retry transient concurrency conflicts.","Avoid concurrent writes to the same authorization by serializing refresh/redemption flows per grant.","Check for duplicated background jobs (e.g. cleanup workers) touching the same authorizations."],"exampleFix":"// before\nawait store.UpdateAsync(authorization, cancellationToken);\n// after\ntry\n{\n    await store.UpdateAsync(authorization, cancellationToken);\n}\ncatch (OpenIddictExceptions.ConcurrencyException)\n{\n    var fresh = await store.FindAsync(authorization.Id, cancellationToken);\n    // re-apply changes to 'fresh' and retry\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    await store.UpdateAsync(authorization, ct);\n}\ncatch (OpenIddictExceptions.ConcurrencyException)\n{\n    var fresh = await store.FindAsync(authorization.Id, ct);\n    // merge/re-apply changes and retry once\n}","preventionTips":["Make token refresh/redemption flows idempotent per authorization.","Limit concurrent refresh requests per grant (single-use refresh tokens).","Ensure only one cleanup/revocation worker runs per instance.","Apply bounded retry-with-reload on concurrency conflicts."],"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"}