bitwarden/server · error · ConflictException
Organization already belongs to a provider.
Error message
Organization already belongs to a provider.
What it means
Thrown by ProviderBillingService.AddExistingOrganization when a ProviderOrganization already exists for the organization (GetByOrganizationId returns non-null). This is the billing-layer equivalent of the admin-layer uniqueness check and uses ConflictException (HTTP 409), reflecting that the org's current state conflicts with the requested operation.
Source
Thrown at bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs:66
IProviderOrganizationRepository providerOrganizationRepository,
IProviderPlanRepository providerPlanRepository,
IProviderUserRepository providerUserRepository,
IStripeAdapter stripeAdapter,
ISubscriberService subscriberService,
ITaxService taxService)
: IProviderBillingService
{
public async Task AddExistingOrganization(
Provider provider,
Organization organization,
string key)
{
var existingProviderOrganization =
await providerOrganizationRepository.GetByOrganizationId(organization.Id);
if (existingProviderOrganization != null)
{
throw new ConflictException("Organization already belongs to a provider.");
}
await priceIncreaseScheduler.Release(
organization.GatewayCustomerId,
organization.GatewaySubscriptionId,
organization.Id);
await stripeAdapter.UpdateSubscriptionAsync(organization.GatewaySubscriptionId,
new SubscriptionUpdateOptions { CancelAtPeriodEnd = false });
var subscription =
await stripeAdapter.CancelSubscriptionAsync(organization.GatewaySubscriptionId,
new SubscriptionCancelOptions
{
CancellationDetails = new SubscriptionCancellationDetailsOptions
{
Comment = $"Organization was added to Provider with ID {provider.Id}"
},View on GitHub (pinned to e93b962371)
Solutions
- Pre-check providerOrganizationRepository.GetByOrganizationId(organization.Id) and short-circuit if non-null.
- Remove/transfer the existing ProviderOrganization before adding.
- Handle HTTP 409 idempotently on the client (treat 'already linked' as success or prompt transfer).
Example fix
// before
await providerBillingService.AddExistingOrganization(provider, organization, key);
// after
var existing = await providerOrganizationRepository.GetByOrganizationId(organization.Id);
if (existing != null)
return Conflict($"Org already linked to provider {existing.ProviderId}.");
await providerBillingService.AddExistingOrganization(provider, organization, key); Defensive patterns
Strategy: validation
Validate before calling
var existing = await providerOrganizationRepository.GetByOrganizationId(organization.Id);
if (existing != null) return Conflict("Already linked."); Try / catch
try { await providerBillingService.AddExistingOrganization(provider, organization, key); }
catch (ConflictException) { /* treat as already-added or prompt transfer */ } Prevention
- Pre-check the org-to-provider link.
- Handle 409 idempotently on the client.
When it happens
Trigger: Calling AddExistingOrganization for an org already linked to any provider; a race where two requests try to add the same org near-simultaneously.
Common situations: Re-running an add that partially succeeded; moving an org between providers without removing the prior link; concurrent admin actions.
Related errors
- Failed to remove organization vault. Please contact support.
- Organization must have at least one confirmed owner.
- Organization already belongs to a provider.
- Organization '{providerOrganization.Id}' not found.
- The organization is subscribed to Secrets Manager. Please co
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/7c9693d56e2f392c.
Report an issue: GitHub.