bitwarden/server · error · BadRequestException
Provider plan not found.
Error message
Provider plan not found.
What it means
Thrown by ProviderBillingService.ChangePlan when providerPlanRepository.GetByIdAsync(providerPlanId) returns null. The referenced provider plan does not exist (deleted, wrong ID, or not yet created). BadRequestException (HTTP 400).
Source
Thrown at bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs:175
Currency = "USD",
Description = $"Unused, prorated time for client organization with ID {organization.Id}."
});
}
await eventService.LogProviderOrganizationEventAsync(
providerOrganization,
EventType.ProviderOrganization_Added);
}
public async Task ChangePlan(ChangeProviderPlanCommand command)
{
var (provider, providerPlanId, newPlanType) = command;
var providerPlan = await providerPlanRepository.GetByIdAsync(providerPlanId);
if (providerPlan == null)
{
throw new BadRequestException("Provider plan not found.");
}
if (providerPlan.PlanType == newPlanType)
{
return;
}
var subscription = await subscriberService.GetSubscriptionOrThrow(provider);
var oldPriceId = ProviderPriceAdapter.GetPriceId(provider, subscription, providerPlan.PlanType);
var newPriceId = ProviderPriceAdapter.GetPriceId(provider, subscription, newPlanType);
providerPlan.PlanType = newPlanType;
await providerPlanRepository.ReplaceAsync(providerPlan);
var oldSubscriptionItem = subscription.Items.SingleOrDefault(x => x.Price.Id == oldPriceId);
var updateOptions = new SubscriptionUpdateOptionsView on GitHub (pinned to e93b962371)
Solutions
- Look up the provider's current plans and use the live providerPlanId before calling ChangePlan.
- Verify providerPlan.ProviderId matches the intended provider.
- If no plan exists, create the provider plan first.
Example fix
// before
await providerBillingService.ChangePlan(new ChangeProviderPlanCommand(provider, planIdGuess, newType));
// after
var plan = await providerPlanRepository.GetByProviderAsync(provider.Id)
.FirstOrDefault(p => p.PlanType == currentType);
if (plan == null) return NotFound("Provider plan not found.");
await providerBillingService.ChangePlan(new ChangeProviderPlanCommand(provider, plan.Id, newType)); Defensive patterns
Strategy: validation
Validate before calling
var plan = await providerPlanRepository.GetByIdAsync(providerPlanId);
if (plan == null) return NotFound("Provider plan not found."); Prevention
- Look up the live providerPlanId for the provider before calling ChangePlan.
- Distinguish providerId from providerPlanId in payloads.
When it happens
Trigger: Calling ChangePlan with a providerPlanId that does not match any ProviderPlan row; passing a provider's ID where a plan ID is expected; referencing a plan from a different provider.
Common situations: Stale plan ID cached in the UI; a provider whose plans were reset/recreated; client confusion between providerId and providerPlanId; an ID copied from another environment.
Related errors
- The organization is subscribed to Secrets Manager. Please co
- Managed Service Providers cannot manage organizations with t
- Business Unit Providers cannot manage organizations with the
- Providers cannot manage organizations with the requested pla
- Failed to remove organization vault. Please contact support.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/52460afa4e0d824e.
Report an issue: GitHub.