bitwarden/server · warning · BadRequestException
Already accepted.
Error message
Already accepted.
What it means
Thrown inside AcceptUserAsync when the ProviderUser's Status is not Invited — the user already accepted or was confirmed. Acceptance is a one-time state transition. BadRequestException (HTTP 400).
Source
Thrown at bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs:255
await SendInviteAsync(providerUser, provider);
result.Add(Tuple.Create(providerUser, ""));
}
return result;
}
public async Task<ProviderUser> AcceptUserAsync(Guid providerUserId, User user, string token)
{
var providerUser = await _providerUserRepository.GetByIdAsync(providerUserId);
if (providerUser == null)
{
throw new BadRequestException("User invalid.");
}
if (providerUser.Status != ProviderUserStatusType.Invited)
{
throw new BadRequestException("Already accepted.");
}
if (!CoreHelpers.TokenIsValid("ProviderUserInvite", _dataProtector, token, user.Email, providerUser.Id,
_globalSettings.OrganizationInviteExpirationHours))
{
throw new BadRequestException("Invalid token.");
}
if (string.IsNullOrWhiteSpace(providerUser.Email) ||
!providerUser.Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase))
{
throw new BadRequestException("User email does not match invite.");
}
var organizationAutoConfirmPolicyRequirement = await _policyRequirementQuery
.GetAsync<AutomaticUserConfirmationPolicyRequirement>(user.Id);
if (organizationAutoConfirmPolicyRequirementView on GitHub (pinned to e93b962371)
Solutions
- Check Status == ProviderUserStatusType.Invited before calling AcceptUserAsync.
- Treat already-accepted as an idempotent success/no-op in the UI.
- Disable the accept button after first use.
Example fix
// before await _providerService.AcceptUserAsync(providerUserId, user, token); // after if (providerUser.Status != ProviderUserStatusType.Invited) return; // already accepted await _providerService.AcceptUserAsync(providerUserId, user, token);
Defensive patterns
Strategy: validation
Validate before calling
var providerUser = await _providerUserRepository.GetByIdAsync(providerUserId);
if (providerUser is { Status: not ProviderUserStatusType.Invited })
return; // already accepted — idempotent Type guard
static bool IsInviteAwaitingAcceptance(ProviderUser? pu) =>
pu is { Status: ProviderUserStatusType.Invited }; Try / catch
try { await _providerService.AcceptUserAsync(providerUserId, user, token); }
catch (BadRequestException ex) when (ex.Message == "Already accepted.")
{ /* treat as success */ } Prevention
- Check Status == Invited before calling AcceptUserAsync.
- Make the accept flow idempotent in the UI.
- Disable the accept control after first use.
When it happens
Trigger: Clicking an already-used accept link; double-submit; the user was already confirmed by a provider admin.
Common situations: Resent/reloaded accept URL; race between self-accept and admin confirmation.
Related errors
- Provider is already setup.
- Invalid permissions.
- User invalid.
- User email does not match invite.
- Invalid user.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/2a80c4daf5a2ad6e.
Report an issue: GitHub.