bitwarden/server · error · BadRequestException
Can only revoke a sponsorship you granted.
Error message
Can only revoke a sponsorship you granted.
What it means
Thrown (HTTP 400) on DELETE /{sponsoringOrganizationId} when the current user's id does not equal the org user's UserId (or orgUser is null). Only the specific org member who originally granted the sponsorship may revoke it via this endpoint.
Source
Thrown at src/Api/Billing/Controllers/OrganizationSponsorshipsController.cs:239
{
throw new BadRequestException("Invalid Billing Sync Key");
}
var (syncResponseData, offersToSend) = await _syncSponsorshipsCommand.SyncOrganization(sponsoringOrg, model.ToOrganizationSponsorshipSync().SponsorshipsBatch);
await _sendSponsorshipOfferCommand.BulkSendSponsorshipOfferAsync(sponsoringOrg.DisplayName(), offersToSend);
return new OrganizationSponsorshipSyncResponseModel(syncResponseData);
}
[Authorize("Application")]
[HttpDelete("{sponsoringOrganizationId}")]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task RevokeSponsorship(Guid sponsoringOrganizationId)
{
var orgUser = await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrganizationId, _currentContext.UserId ?? default);
if (_currentContext.UserId != orgUser?.UserId)
{
throw new BadRequestException("Can only revoke a sponsorship you granted.");
}
var existingOrgSponsorship = await _organizationSponsorshipRepository
.GetBySponsoringOrganizationUserIdAsync(orgUser.Id);
await _revokeSponsorshipCommand.RevokeSponsorshipAsync(existingOrgSponsorship);
}
[Authorize("Application")]
[HttpPost("{sponsoringOrganizationId}/delete")]
[Obsolete("This endpoint is deprecated. Use DELETE /{sponsoringOrganizationId} instead.")]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task PostRevokeSponsorship(Guid sponsoringOrganizationId)
{
await RevokeSponsorship(sponsoringOrganizationId);
}
[Authorize("Application")]View on GitHub (pinned to e93b962371)
Solutions
- Have the original granting org user perform the revoke.
- Use the admin-initiated revoke endpoint (DELETE .../{organizationId}/{sponsoredFriendlyName}/revoke) which requires ManageUsers instead.
- Confirm the current user is still a member of the sponsoring org.
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the current user is the org member who granted the sponsorship before calling revoke.
const orgUser = await getOrgUser(sponsoringOrgId, currentUserId);
if (!orgUser || orgUser.userId !== currentUserId) {
throw new Error('Only the granting user can revoke this sponsorship');
} Try / catch
try {
await del(`/organization-sponsorships/${sponsoringOrgId}`);
} catch (e) {
if (e.isBadRequest && /sponsorship you granted/i.test(e.message)) {
routeToAdminRevokeEndpoint(); // use the ManageUsers admin-initiated revoke instead
} else { throw e; }
} Prevention
- Determine whether the current user is the original granter before showing self-service revoke.
- Offer the admin-initiated revoke endpoint to org admins with ManageUsers.
- Track which org user granted each sponsorship in the UI.
When it happens
Trigger: A different admin than the original granter attempts the revoke; orgUser is null because the current user is not a member of that org; the original granter's membership was removed.
Common situations: Original granter left the org; multiple admins and a non-granter tries to revoke.
Related errors
- Free Bitwarden Families sponsorship has been disabled by you
- Can only redeem sponsorship for an organization you own.
- Only the owner of an organization can remove sponsorship.
- Failed to remove organization vault. Please contact support.
- Organization must have at least one confirmed owner.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/e4a484fd8bc91fe7.
Report an issue: GitHub.