{"record":{"id":"96bbe0de1fdbaeb8","repo":"bitwarden/server","slug":"only-the-owner-of-an-organization-can-remove-spons","errorCode":null,"errorMessage":"Only the owner of an organization can remove sponsorship.","messagePattern":"Only the owner of an organization can remove sponsorship\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Billing/Controllers/OrganizationSponsorshipsController.cs","lineNumber":280,"sourceCode":"    {\n        var sponsorships = await _organizationSponsorshipRepository.GetManyBySponsoringOrganizationAsync(sponsoringOrgId);\n        var existingOrgSponsorship = sponsorships.FirstOrDefault(s => s.FriendlyName != null && s.FriendlyName.Equals(sponsoredFriendlyName, StringComparison.OrdinalIgnoreCase));\n        if (existingOrgSponsorship == null)\n        {\n            throw new BadRequestException(\"The specified sponsored organization could not be found under the given sponsoring organization.\");\n        }\n        await _revokeSponsorshipCommand.RevokeSponsorshipAsync(existingOrgSponsorship);\n    }\n\n    [Authorize(\"Application\")]\n    [HttpDelete(\"sponsored/{sponsoredOrgId}\")]\n    [SelfHosted(NotSelfHostedOnly = true)]\n    public async Task RemoveSponsorship(Guid sponsoredOrgId)\n    {\n\n        if (!await _currentContext.OrganizationOwner(sponsoredOrgId))\n        {\n            throw new BadRequestException(\"Only the owner of an organization can remove sponsorship.\");\n        }\n\n        var existingOrgSponsorship = await _organizationSponsorshipRepository\n            .GetBySponsoredOrganizationIdAsync(sponsoredOrgId);\n\n        await _removeSponsorshipCommand.RemoveSponsorshipAsync(existingOrgSponsorship);\n    }\n\n    [Authorize(\"Application\")]\n    [HttpPost(\"sponsored/{sponsoredOrgId}/remove\")]\n    [Obsolete(\"This endpoint is deprecated. Use DELETE /sponsored/{sponsoredOrgId} instead.\")]\n    [SelfHosted(NotSelfHostedOnly = true)]\n    public async Task PostRemoveSponsorship(Guid sponsoredOrgId)\n    {\n        await RemoveSponsorship(sponsoredOrgId);\n    }\n\n    [HttpGet(\"{sponsoringOrgId}/sync-status\")]","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Billing/Controllers/OrganizationSponsorshipsController.cs#L262-L298","documentation":"Thrown (HTTP 400) on DELETE /sponsored/{sponsoredOrgId} when _currentContext.OrganizationOwner(sponsoredOrgId) returns false. Only an Owner of the sponsored organization may remove its sponsorship.","triggerScenarios":"A non-owner user (Admin, custom role, member) attempts sponsorship removal; the user is an owner of a different org.","commonSituations":"Admin vs Owner role confusion; user belongs to several orgs and targets the wrong one.","solutions":["Have an Owner of the sponsored organization perform the removal.","Elevate the intended user to the Owner role, then retry.","Confirm the sponsoredOrgId corresponds to an org the user owns."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm ownership before offering removal.\nconst isOwner = await isOrgOwner(sponsoredOrgId);\nif (!isOwner) throw new Error('Only an Owner of the sponsored org can remove sponsorship');","typeGuard":null,"tryCatchPattern":"try {\n  await del(`/organization-sponsorships/sponsored/${sponsoredOrgId}`);\n} catch (e) {\n  if (e.isBadRequest && /owner of an organization/i.test(e.message)) {\n    prompt('Ask an Owner of this organization to remove the sponsorship.');\n  } else { throw e; }\n}","preventionTips":["Gate the remove-sponsorship action on the Owner role for the sponsored org.","Clarify Admin vs Owner permissions in the UI.","Confirm sponsoredOrgId maps to an org the user owns."],"tags":["billing","sponsorship","authorization","organization","rbac"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}