{"record":{"id":"28f570f6092aef72","repo":"bitwarden/server","slug":"invalid-user","errorCode":null,"errorMessage":"Invalid user.","messagePattern":"Invalid user\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs","lineNumber":321,"sourceCode":"        var provider = await _providerRepository.GetByIdAsync(providerId);\n        var users = await _userRepository.GetManyAsync(validOrganizationUserIds);\n\n        var keyedFilteredUsers = validProviderUsers.ToDictionary(u => u.UserId.Value, u => u);\n\n        var result = new List<Tuple<ProviderUser, string>>();\n        var events = new List<(ProviderUser, EventType, DateTime?)>();\n\n        foreach (var user in users)\n        {\n            if (!keyedFilteredUsers.TryGetValue(user.Id, out var providerUser))\n            {\n                continue;\n            }\n            try\n            {\n                if (providerUser.Status != ProviderUserStatusType.Accepted || providerUser.ProviderId != providerId)\n                {\n                    throw new BadRequestException(\"Invalid user.\");\n                }\n\n                var organizationAutoConfirmPolicyRequirement = await _policyRequirementQuery\n                    .GetAsync<AutomaticUserConfirmationPolicyRequirement>(user.Id);\n\n                if (organizationAutoConfirmPolicyRequirement\n                    .CannotJoinProvider())\n                {\n                    result.Add(Tuple.Create(providerUser, new UserCannotJoinProvider().Message));\n                    continue;\n                }\n\n                providerUser.Status = ProviderUserStatusType.Confirmed;\n                providerUser.Key = keys[providerUser.Id];\n                providerUser.Email = null;\n\n                await _providerUserRepository.ReplaceAsync(providerUser);\n                events.Add((providerUser, EventType.ProviderUser_Confirmed, null));","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs#L303-L339","documentation":"Thrown inside the per-user loop of ConfirmUsersAsync when a ProviderUser's Status is not Accepted or its ProviderId does not match the target provider. Note this is caught locally and recorded as a per-user error tuple in the result list rather than failing the entire batch. BadRequestException (HTTP 400).","triggerScenarios":"Attempting to confirm a user who has not yet accepted (still Invited), or who belongs to a different provider.","commonSituations":"Admin confirms before the user accepts; stale user list shown in the UI; cross-provider Id errors.","solutions":["Filter to only Accepted-status provider users before confirming.","Inspect the returned per-user result tuples to identify which users failed and why.","Refresh the provider user list before the confirm action."],"exampleFix":"// before\nvar results = await _providerService.ConfirmUsersAsync(providerId, keys, confirmingUserId);\n\n// after\nvar validKeys = keys\n    .Where(k => acceptedUsers[k.Key].Status == ProviderUserStatusType.Accepted)\n    .ToDictionary(k => k.Key, k => k.Value);\nvar results = await _providerService.ConfirmUsersAsync(providerId, validKeys, confirmingUserId);","handlingStrategy":"validation","validationCode":"var confirmable = acceptedUsers\n    .Where(pu => pu.Status == ProviderUserStatusType.Accepted && pu.ProviderId == providerId)\n    .ToDictionary(pu => pu.Id, pu => keys[pu.Id]);","typeGuard":"static bool IsConfirmable(ProviderUser pu, Guid providerId) =>\n    pu.Status == ProviderUserStatusType.Accepted && pu.ProviderId == providerId;","tryCatchPattern":"var results = await _providerService.ConfirmUsersAsync(providerId, keys, confirmingUserId);\nvar failures = results.Where(r => !string.IsNullOrEmpty(r.Item2)); // inspect per-user errors","preventionTips":["Only pass Accepted-status provider users to ConfirmUsersAsync.","Inspect per-user result tuples to identify failures.","Refresh the user list before confirming to avoid stale states."],"tags":["provider","confirm","state-machine","batch","bitwarden"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}