{"record":{"id":"7c9693d56e2f392c","repo":"bitwarden/server","slug":"organization-already-belongs-to-a-provider-7c9693","errorCode":null,"errorMessage":"Organization already belongs to a provider.","messagePattern":"Organization already belongs to a provider\\.","errorType":"exception","errorClass":"ConflictException","httpStatus":409,"severity":"error","filePath":"bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs","lineNumber":66,"sourceCode":"    IProviderOrganizationRepository providerOrganizationRepository,\n    IProviderPlanRepository providerPlanRepository,\n    IProviderUserRepository providerUserRepository,\n    IStripeAdapter stripeAdapter,\n    ISubscriberService subscriberService,\n    ITaxService taxService)\n    : IProviderBillingService\n{\n    public async Task AddExistingOrganization(\n        Provider provider,\n        Organization organization,\n        string key)\n    {\n        var existingProviderOrganization =\n            await providerOrganizationRepository.GetByOrganizationId(organization.Id);\n\n        if (existingProviderOrganization != null)\n        {\n            throw new ConflictException(\"Organization already belongs to a provider.\");\n        }\n\n        await priceIncreaseScheduler.Release(\n            organization.GatewayCustomerId,\n            organization.GatewaySubscriptionId,\n            organization.Id);\n\n        await stripeAdapter.UpdateSubscriptionAsync(organization.GatewaySubscriptionId,\n            new SubscriptionUpdateOptions { CancelAtPeriodEnd = false });\n\n        var subscription =\n            await stripeAdapter.CancelSubscriptionAsync(organization.GatewaySubscriptionId,\n                new SubscriptionCancelOptions\n                {\n                    CancellationDetails = new SubscriptionCancellationDetailsOptions\n                    {\n                        Comment = $\"Organization was added to Provider with ID {provider.Id}\"\n                    },","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs#L48-L84","documentation":"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.","triggerScenarios":"Calling AddExistingOrganization for an org already linked to any provider; a race where two requests try to add the same org near-simultaneously.","commonSituations":"Re-running an add that partially succeeded; moving an org between providers without removing the prior link; concurrent admin actions.","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)."],"exampleFix":"// before\nawait providerBillingService.AddExistingOrganization(provider, organization, key);\n\n// after\nvar existing = await providerOrganizationRepository.GetByOrganizationId(organization.Id);\nif (existing != null)\n    return Conflict($\"Org already linked to provider {existing.ProviderId}.\");\nawait providerBillingService.AddExistingOrganization(provider, organization, key);","handlingStrategy":"validation","validationCode":"var existing = await providerOrganizationRepository.GetByOrganizationId(organization.Id);\nif (existing != null) return Conflict(\"Already linked.\");","typeGuard":null,"tryCatchPattern":"try { await providerBillingService.AddExistingOrganization(provider, organization, key); }\ncatch (ConflictException) { /* treat as already-added or prompt transfer */ }","preventionTips":["Pre-check the org-to-provider link.","Handle 409 idempotently on the client."],"tags":["billing","provider","organization","uniqueness","conflict"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}