bitwarden/server · error · BadRequestException
Invalid license key.
Error message
Invalid license key.
What it means
Thrown (HTTP 400) by GET /licenses/user/{id}?key=... when the user exists but the supplied query key does not equal user.LicenseKey. A 2-second Task.Delay is applied before throwing to slow key enumeration. Note: a non-existent user returns null (HTTP 200 with null body), not this error.
Source
Thrown at src/Api/Billing/Controllers/LicensesController.cs:58
_userService = userService;
_organizationRepository = organizationRepository;
_getCloudOrganizationLicenseQuery = getCloudOrganizationLicenseQuery;
_validateBillingSyncKeyCommand = validateBillingSyncKeyCommand;
_currentContext = currentContext;
}
[HttpGet("user/{id}")]
public async Task<UserLicense> GetUser(string id, [FromQuery] string key)
{
var user = await _userRepository.GetByIdAsync(new Guid(id));
if (user == null)
{
return null;
}
else if (!user.LicenseKey.Equals(key))
{
await Task.Delay(2000);
throw new BadRequestException("Invalid license key.");
}
var license = await _userService.GenerateLicenseAsync(user, null);
return license;
}
/// <summary>
/// Used by self-hosted installations to get an updated license file
/// </summary>
[HttpGet("organization/{id}")]
public async Task<OrganizationLicense> OrganizationSync(string id, [FromBody] SelfHostedOrganizationLicenseRequestModel model)
{
var organization = await _organizationRepository.GetByIdAsync(new Guid(id));
if (organization == null)
{
throw new NotFoundException("Organization not found.");
}
View on GitHub (pinned to e93b962371)
Solutions
- Retrieve the current license key from the user's billing settings in the cloud and use it as the ?key value.
- Update any stored configuration referencing the old key.
- Double-check there are no trailing spaces or encoding artifacts in the key.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the configured license key is non-empty and matches the expected format before calling.
if (!licenseKey || licenseKey.length < EXPECTED_MIN_LEN) {
throw new Error('License key is missing or truncated');
} Try / catch
try {
const lic = await get(`/licenses/user/${id}?key=${encodeURIComponent(key)}`);
} catch (e) {
if (e.isBadRequest && /invalid license key/i.test(e.message)) {
await refreshLicenseKeyFromCloud(); // fetch current key, then retry once
} else { throw e; }
} Prevention
- Store the license key in version-controlled config and update it when re-issued.
- Copy keys via clipboard to avoid transcription errors.
- Regenerate the key in the cloud portal if its provenance is uncertain.
When it happens
Trigger: Wrong or stale license key in the ?key= query parameter; the license key was regenerated; caller knows a valid user id but not its current key.
Common situations: License key rotated in the cloud portal but the self-hosted retrieval config still holds the old key; transcription/copy error in the key.
Related errors
- Invalid Billing Sync Key
- Invalid Billing Sync Key
- NoSeatsAvailable
- User verification failed.
- Invalid license
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/b89ee476a4591fec.
Report an issue: GitHub.