bitwarden/server · error · BadRequestException
Invalid owner.
Error message
Invalid owner.
What it means
Thrown inside CompleteSetupAsync when _userService.GetUserByIdAsync(ownerUserId) returns null. The setup flow needs the owner to exist to validate the invite token against their email and to configure their ProviderUser record. BadRequestException (HTTP 400).
Source
Thrown at bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs:109
_globalSettings = globalSettings;
_dataProtector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector");
_currentContext = currentContext;
_stripeAdapter = stripeAdapter;
_providerDeleteTokenDataFactory = providerDeleteTokenDataFactory;
_organizationAbilityCacheService = organizationAbilityCacheService;
_providerAbilityCacheService = providerAbilityCacheService;
_providerBillingService = providerBillingService;
_pricingClient = pricingClient;
_providerClientOrganizationSignUpCommand = providerClientOrganizationSignUpCommand;
_policyRequirementQuery = policyRequirementQuery;
}
public async Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key, TokenizedPaymentMethod paymentMethod, BillingAddress billingAddress)
{
var owner = await _userService.GetUserByIdAsync(ownerUserId);
if (owner == null)
{
throw new BadRequestException("Invalid owner.");
}
if (provider.Status != ProviderStatusType.Pending)
{
throw new BadRequestException("Provider is already setup.");
}
if (!CoreHelpers.TokenIsValid("ProviderSetupInvite", _dataProtector, token, owner.Email, provider.Id,
_globalSettings.OrganizationInviteExpirationHours))
{
throw new BadRequestException("Invalid token.");
}
var providerUser = await _providerUserRepository.GetByProviderUserAsync(provider.Id, ownerUserId);
if (!(providerUser is { Type: ProviderUserType.ProviderAdmin }))
{
throw new BadRequestException("Invalid owner.");
}View on GitHub (pinned to e93b962371)
Solutions
- Verify the user exists before invoking setup (call IUserService.GetUserByIdAsync).
- Re-issue the setup invite for a valid existing user.
- Ensure the ownerUserId comes from the authenticated session, not a stale link.
Defensive patterns
Strategy: validation
Validate before calling
var owner = await _userService.GetUserByIdAsync(ownerUserId);
if (owner == null)
throw new InvalidOperationException($"Owner user '{ownerUserId}' does not exist."); Try / catch
try { await _providerService.CompleteSetupAsync(provider, ownerUserId, token, key, payment, billing); }
catch (BadRequestException ex) when (ex.Message == "Invalid owner.")
{ /* owner user missing — re-issue invite for a valid user */ } Prevention
- Derive ownerUserId from the authenticated session, not a stale link.
- Re-verify user existence right before setup.
- Clean up stale setup links when users are deleted.
When it happens
Trigger: CompleteSetupAsync invoked with an ownerUserId that was deleted, never existed, or belongs to a different environment.
Common situations: Stale setup link after the owner account was deleted; test fixtures with wrong user IDs; cross-environment ID leakage.
Related errors
- Invalid owner. Owner must be an existing Bitwarden user.
- Failed to remove organization vault. Please contact support.
- Organization must have at least one confirmed owner.
- Provider is already setup.
- Invalid token.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/e35448b843023f70.
Report an issue: GitHub.