bitwarden/server · warning · BadRequestException
Provider is already setup.
Error message
Provider is already setup.
What it means
Thrown inside CompleteSetupAsync when provider.Status is not Pending, meaning setup has already been completed. Setup is a one-time state transition from Pending to Billable. BadRequestException (HTTP 400).
Source
Thrown at bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs:114
_organizationAbilityCacheService = organizationAbilityCacheService;
_providerAbilityCacheService = providerAbilityCacheService;
_providerBillingService = providerBillingService;
_pricingClient = pricingClient;
_providerClientOrganizationSignUpCommand = providerClientOrganizationSignUpCommand;
_policyRequirementQuery = policyRequirementQuery;
}
public async Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key, TokenizedPaymentMethod paymentMethod, BillingAddress billingAddress)
{
var owner = await _userService.GetUserByIdAsync(ownerUserId);
if (owner == null)
{
throw new BadRequestException("Invalid owner.");
}
if (provider.Status != ProviderStatusType.Pending)
{
throw new BadRequestException("Provider is already setup.");
}
if (!CoreHelpers.TokenIsValid("ProviderSetupInvite", _dataProtector, token, owner.Email, provider.Id,
_globalSettings.OrganizationInviteExpirationHours))
{
throw new BadRequestException("Invalid token.");
}
var providerUser = await _providerUserRepository.GetByProviderUserAsync(provider.Id, ownerUserId);
if (!(providerUser is { Type: ProviderUserType.ProviderAdmin }))
{
throw new BadRequestException("Invalid owner.");
}
var organizationAutoConfirmPolicyRequirement = await _policyRequirementQuery
.GetAsync<AutomaticUserConfirmationPolicyRequirement>(ownerUserId);
if (organizationAutoConfirmPolicyRequirementView on GitHub (pinned to e93b962371)
Solutions
- Check provider.Status == ProviderStatusType.Pending before calling.
- Treat already-setup as an idempotent success/no-op in the caller rather than an error.
- Guard the client submit button to prevent double-posting.
Example fix
// before await _providerService.CompleteSetupAsync(provider, ownerUserId, token, key, payment, billing); // after if (provider.Status == ProviderStatusType.Billable) return; // already done await _providerService.CompleteSetupAsync(provider, ownerUserId, token, key, payment, billing);
Defensive patterns
Strategy: validation
Validate before calling
if (provider.Status != ProviderStatusType.Pending)
return; // already set up — idempotent no-op Try / catch
try { await _providerService.CompleteSetupAsync(provider, ownerUserId, token, key, payment, billing); }
catch (BadRequestException ex) when (ex.Message.Contains("already setup"))
{ /* treat as success — provider is configured */ } Prevention
- Check provider.Status == Pending before setup.
- Make the setup endpoint idempotent for already-configured providers.
- Disable the submit button client-side after first success.
When it happens
Trigger: Calling CompleteSetupAsync a second time (double-submit), or on a provider already configured/Billable.
Common situations: Duplicate/retried POST after a successful setup; UI resubmission; concurrent setup attempts.
Related errors
- Already accepted.
- Invalid owner.
- Invalid token.
- An organization the user is a part of has enabled Automatic
- Invalid user.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/2833010bfb8bd1ce.
Report an issue: GitHub.