{"record":{"id":"5d7435b5f7fee921","repo":"bitwarden/server","slug":"organization-must-have-at-least-one-confirmed-owne","errorCode":null,"errorMessage":"Organization must have at least one confirmed owner.","messagePattern":"Organization must have at least one confirmed owner\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"bitwarden_license/src/Commercial.Core/AdminConsole/Providers/RemoveOrganizationFromProviderCommand.cs","lineNumber":79,"sourceCode":"    public async Task RemoveOrganizationFromProvider(\n        Provider provider,\n        ProviderOrganization providerOrganization,\n        Organization organization)\n    {\n        if (provider == null ||\n            providerOrganization == null ||\n            organization == null ||\n            providerOrganization.ProviderId != provider.Id)\n        {\n            throw new BadRequestException(new FailedToRemoveOrganizationFromProviderError().Message);\n        }\n\n        if (!await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(\n                providerOrganization.OrganizationId,\n                [],\n                includeProvider: false))\n        {\n            throw new BadRequestException(new OrgMustHaveConfirmedOwner().Message);\n        }\n\n        var organizationOwnerEmails =\n            (await _organizationRepository.GetOwnerEmailAddressesById(organization.Id)).ToList();\n\n        organization.BillingEmail = organizationOwnerEmails.MinBy(email => email);\n\n        await ResetOrganizationBillingAsync(organization, provider, organizationOwnerEmails);\n\n        await _organizationRepository.ReplaceAsync(organization);\n\n        await _providerOrganizationRepository.DeleteAsync(providerOrganization);\n\n        await _eventService.LogProviderOrganizationEventAsync(\n            providerOrganization,\n            EventType.ProviderOrganization_Removed);\n    }\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/bitwarden_license/src/Commercial.Core/AdminConsole/Providers/RemoveOrganizationFromProviderCommand.cs#L61-L97","documentation":"Thrown by RemoveOrganizationFromProvider when HasConfirmedOwnersExceptAsync returns false with includeProvider: false, meaning the organization has no confirmed owners outside the provider's scope. Detaching such an org would orphan it with nobody able to manage it. BadRequestException (HTTP 400); message from OrgMustHaveConfirmedOwner.","triggerScenarios":"Detaching an organization whose only confirmed owners were established through the provider; once unlinked, no direct confirmed org owner would remain.","commonSituations":"MSP-managed orgs where all owners were auto-confirmed via the provider; attempting to unlink without first adding a direct confirmed owner.","solutions":["Confirm at least one organization owner directly on the organization (not via provider) before detaching.","Pre-check with _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(orgId, [], includeProvider: false) and surface a clear message.","Add a direct owner user to the org first if none exists."],"exampleFix":"// before\nawait _removeOrgCommand.RemoveOrganizationFromProvider(provider, providerOrg, org);\n\n// after\nif (!await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(org.Id, [], includeProvider: false))\n    throw new InvalidOperationException(\"Add and confirm a direct org owner before unlinking from the provider.\");\nawait _removeOrgCommand.RemoveOrganizationFromProvider(provider, providerOrg, org);","handlingStrategy":"validation","validationCode":"if (!await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(\n        organization.Id, [], includeProvider: false))\n    throw new InvalidOperationException(\"Organization must have a confirmed owner before unlinking from the provider.\");","typeGuard":null,"tryCatchPattern":"try { await _removeOrgCommand.RemoveOrganizationFromProvider(provider, providerOrg, org); }\ncatch (BadRequestException ex) when (ex.Message.Contains(\"confirmed owner\"))\n{ /* prompt admin to add/confirm a direct owner first */ }","preventionTips":["Add and confirm a direct org owner before unlinking.","Pre-check HasConfirmedOwnersExceptAsync in the UI to warn early.","Never rely solely on provider-mediated owners for an org you plan to detach."],"tags":["provider","organization","ownership","validation","billing","bitwarden"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}