{"record":{"id":"32ed47f92cd789ae","repo":"fullstackhero/dotnet-starter-kit","slug":"toggle-status-failed","errorCode":null,"errorMessage":"Toggle status failed","messagePattern":"Toggle status failed","errorType":"exception","errorClass":"CustomException","httpStatus":400,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/UserStatusService.cs","lineNumber":133,"sourceCode":"    {\n        if (context.ActivateUser)\n        {\n            context.TargetUser.Activate(context.ActorId.ToString(), context.TenantId);\n        }\n        else\n        {\n            context.TargetUser.Deactivate(context.ActorId.ToString(), \"Status toggled by administrator\", context.TenantId);\n        }\n    }\n\n    private async Task SaveAndAuditAsync(\n        ToggleStatusContext context,\n        CancellationToken cancellationToken)\n    {\n        var result = await userManager.UpdateAsync(context.TargetUser);\n        if (!result.Succeeded)\n        {\n            throw new CustomException(\"Toggle status failed\", result.Errors.Select(e => e.Description).ToList(), HttpStatusCode.BadRequest);\n        }\n\n        await auditClient.WriteActivityAsync(\n            ActivityKind.Command,\n            name: \"ToggleUserStatus\",\n            statusCode: 204,\n            durationMs: 0,\n            captured: BodyCapture.None,\n            requestSize: 0,\n            responseSize: 0,\n            requestPreview: new { actorId = context.ActorId.ToString(), targetUserId = context.TargetUser.Id, action = context.ActivateUser ? \"activate\" : \"deactivate\", tenant = context.TenantId ?? \"unknown\" },\n            responsePreview: new { outcome = \"success\" },\n            severity: AuditSeverity.Information,\n            source: \"Identity\",\n            ct: cancellationToken).ConfigureAwait(false);\n    }\n\n    private async Task AuditPolicyFailureAsync(","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/UserStatusService.cs#L115-L151","documentation":"UserStatusService.SaveAndAuditAsync throws CustomException with 400 BadRequest (\"Toggle status failed\") when userManager.UpdateAsync fails to persist the status change, i.e. the Identity UpdateResult is not Succeeded. The individual Identity errors are attached to the exception as its error list.","triggerScenarios":"Concurrent modification of the same user row (ConcurrencyStamp mismatch), store/provider-level validation failure during UpdateAsync, or database write issues surfaced through the Identity result.","commonSituations":"Two admins toggling the same user simultaneously; background jobs updating the user while an admin edits it; custom IUserValidator rules rejecting the change; DB connectivity problems.","solutions":["Read the error list on the exception (result.Errors descriptions) for the concrete cause and fix accordingly.","Retry the toggle: a concurrency conflict resolves once the other write completes.","Reload the user (fresh ConcurrencyStamp) and reapply the change.","Check database connectivity/locks if errors persist."],"exampleFix":"// before\nvar result = await userManager.UpdateAsync(user); // stale entity -> concurrency failure\n// after\nuser = await userManager.FindByIdAsync(userId); // reload fresh stamp\nuser.IsActive = !user.IsActive;\nvar result = await userManager.UpdateAsync(user);\nif (!result.Succeeded) throw new CustomException(\"Toggle status failed\", result.Errors.Select(e => e.Description).ToArray(), HttpStatusCode.BadRequest);","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await mediator.Send(cmd); }\ncatch (CustomException ex) when (ex.ErrorMessages.Any(m => m.Contains(\"concurrency\", StringComparison.OrdinalIgnoreCase)))\n{ /* reload user (fresh ConcurrencyStamp) and retry once */ }","preventionTips":["Avoid long-lived detached user entities; reload before updating.","Serialize admin operations on the same user (optimistic UI locking).","Surface result.Errors to the caller instead of swallowing them.","Monitor for repeated failures indicating a systemic store issue."],"tags":["identity","persistence","concurrency","bad-request"],"backgroundTag":"database-write-failed","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}