bitwarden/server · error · BadRequestException

The specified sponsored organization could not be found unde

Error message

The specified sponsored organization could not be found under the given sponsoring organization.

What it means

Thrown by the admin-initiated DELETE /sponsorships/{organizationId}/{sponsoredFriendlyName}/revoke when no sponsorship under the sponsoring org has a FriendlyName matching sponsoredFriendlyName (case-insensitive). The caller has ManageUsers authorization, the sponsoring org exists, but the named sponsorship does not.

Source

Thrown at src/Api/Controllers/SelfHosted/SelfHostedOrganizationSponsorshipsController.cs:100

        await _revokeSponsorshipCommand.RevokeSponsorshipAsync(existingOrgSponsorship);
    }

    [HttpPost("{sponsoringOrgId}/delete")]
    [Obsolete("This endpoint is deprecated. Use DELETE /{sponsoringOrgId} instead.")]
    public async Task PostRevokeSponsorship(Guid sponsoringOrgId)
    {
        await RevokeSponsorship(sponsoringOrgId);
    }

    [Authorize<ManageUsersRequirement>]
    [HttpDelete("{organizationId}/{sponsoredFriendlyName}/revoke")]
    public async Task AdminInitiatedRevokeSponsorshipAsync([FromRoute(Name = "organizationId")] Guid sponsoringOrgId, string sponsoredFriendlyName)
    {
        var sponsorships = await _organizationSponsorshipRepository.GetManyBySponsoringOrganizationAsync(sponsoringOrgId);
        var existingOrgSponsorship = sponsorships.FirstOrDefault(s => s.FriendlyName != null && s.FriendlyName.Equals(sponsoredFriendlyName, StringComparison.OrdinalIgnoreCase));
        if (existingOrgSponsorship == null)
        {
            throw new BadRequestException("The specified sponsored organization could not be found under the given sponsoring organization.");
        }
        await _revokeSponsorshipCommand.RevokeSponsorshipAsync(existingOrgSponsorship);
    }

    [Authorize("Application")]
    [HttpGet("{orgId}/sponsored")]
    public async Task<ListResponseModel<OrganizationSponsorshipInvitesResponseModel>> GetSponsoredOrganizations(Guid orgId)
    {
        var sponsoringOrg = await _organizationRepository.GetByIdAsync(orgId);
        if (sponsoringOrg == null)
        {
            throw new NotFoundException();
        }

        var authorizationResult = await _authorizationService.AuthorizeAsync(User, orgId, new ManageUsersRequirement());
        if (!authorizationResult.Succeeded)
        {
            throw new UnauthorizedAccessException();

View on GitHub (pinned to e93b962371)

Solutions

  1. List sponsorships for the org (GET .../{orgId}/sponsored) and copy the exact current FriendlyName.
  2. Trim whitespace from the friendly name before sending.
  3. If already revoked, no action is needed; surface that state to the operator.

Example fix

// before: guessed friendly name
//   DELETE /sponsorships/{orgId}/{guessedName}/revoke
//
// after: look up the exact friendly name first
var sponsored = (await GetSponsoredOrganizations(orgId))
  .First(s => string.Equals(s.FriendlyName, nameWanted, StringComparison.OrdinalIgnoreCase));
await AdminRevokeAsync(orgId, sponsored.FriendlyName);
Defensive patterns

Strategy: validation

Validate before calling

// Look up the exact FriendlyName before admin-initiated revoke
const sponsored = await getSponsoredOrganizations(orgId);
const match = sponsored.find(s => (s.friendlyName ?? '').trim().toLowerCase() === name.trim().toLowerCase());
if (!match) throw new Error('No sponsorship with that friendly name');
await adminRevoke(orgId, match.friendlyName);

Type guard

function isMatchingFriendlyName(sponsored, name) {
  return Array.isArray(sponsored) && sponsored.some(s =>
    typeof s.friendlyName === 'string' &&
    s.friendlyName.trim().toLowerCase() === String(name).trim().toLowerCase());
}

Try / catch

try {
  await adminRevoke(orgId, friendlyName);
} catch (e) {
  if (e.status === 400 && /could not be found/i.test(e.message)) {
    await refreshSponsorshipListAndPrompt(orgId);
  } else throw e;
}

Prevention

When it happens

Trigger: Revoke with a friendly name that has a typo, has been renamed, was already revoked/deleted, or differs in case beyond what OrdinalIgnoreCase covers (it does cover case). Sponsored org may exist under a different friendly name.

Common situations: Admin copy-pastes a stale friendly name from an old list; the sponsorship was already revoked in another session; friendly name has trailing spaces stored; rename of the sponsored org changed FriendlyName.

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/6f61e6aeca1daa32. Report an issue: GitHub.