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

  1. Verify the user exists before invoking setup (call IUserService.GetUserByIdAsync).
  2. Re-issue the setup invite for a valid existing user.
  3. 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

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


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