{"record":{"id":"87193588d1745e85","repo":"bitwarden/server","slug":"user-not-found-871935","errorCode":null,"errorMessage":"User not found.","messagePattern":"User not found\\.","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"bitwarden_license/src/Scim/Users/PatchUserCommand.cs","lineNumber":35,"sourceCode":"    private readonly IRevokeOrganizationUserCommand _revokeOrganizationUserCommand;\n\n    public PatchUserCommand(IOrganizationUserRepository organizationUserRepository,\n        IRestoreOrganizationUserCommand restoreOrganizationUserCommand,\n        ILogger<PatchUserCommand> logger,\n        IRevokeOrganizationUserCommand revokeOrganizationUserCommand)\n    {\n        _organizationUserRepository = organizationUserRepository;\n        _restoreOrganizationUserCommand = restoreOrganizationUserCommand;\n        _logger = logger;\n        _revokeOrganizationUserCommand = revokeOrganizationUserCommand;\n    }\n\n    public async Task PatchUserAsync(Guid organizationId, Guid id, ScimPatchModel model)\n    {\n        var orgUser = await _organizationUserRepository.GetByIdAsync(id);\n        if (orgUser == null || orgUser.OrganizationId != organizationId)\n        {\n            throw new NotFoundException(\"User not found.\");\n        }\n\n        var operationHandled = false;\n        foreach (var operation in model.Operations)\n        {\n            // Replace operations\n            if (operation.Op?.ToLowerInvariant() == PatchOps.Replace)\n            {\n                // Active from path\n                if (operation.Path?.ToLowerInvariant() == \"active\")\n                {\n                    var active = operation.Value.ToString()?.ToLowerInvariant();\n                    var handled = await HandleActiveOperationAsync(orgUser, active == \"true\");\n                    if (!operationHandled)\n                    {\n                        operationHandled = handled;\n                    }\n                    // Re-fetch to pick up status changes persisted by restore/revoke","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/bitwarden_license/src/Scim/Users/PatchUserCommand.cs#L17-L53","documentation":"Thrown as a NotFoundException (HTTP 404) by PatchUserCommand.PatchUserAsync when the organization user for {id} does not exist or its OrganizationId does not match the route's organizationId. This is the initial existence check before processing any PATCH operations on the user.","triggerScenarios":"PATCH /v2/{organizationId}/Users/{id} where the organization user was deleted, revoked and purged, or belongs to a different org. IdP sends an update (e.g., deactivate) for a user no longer in Bitwarden.","commonSituations":"User removed from Bitwarden but IdP still tracks them. IdP sends a deactivation PATCH after the user was already deleted. Cross-tenant GUID confusion from wrong SCIM key.","solutions":["List users via GET /v2/{organizationId}/Users to confirm whether the user still exists.","If removed, re-provision via POST or remove the stale reference from the IdP.","Verify the organizationId matches the SCIM token's organization scope.","Re-sync the IdP directory to reconcile."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var existing = await scimClient.GetUserAsync(orgId, userId);\nif (existing == null) { /* user gone — reconcile IdP ref */ return; }\n// only then PATCH","typeGuard":null,"tryCatchPattern":"try { await scimClient.PatchUserAsync(orgId, userId, patchModel); }\ncatch (ScimException ex) when (ex.StatusCode == 404)\n{ /* user removed — delete from IdP or re-provision */ }","preventionTips":["Cache user GUIDs and prune entries that 404.","Run periodic full-sync reconciliation.","Never blindly retry PATCH on a 404 — the user is gone."],"tags":["scim","not-found","users","http-404","patch","provisioning"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}