bitwarden/server · error · BadRequestException
Cannot verify license file.
Error message
Cannot verify license file.
What it means
Thrown by ValidateBillingSyncConfig when ReadOrganizationLicenseAsync returns null (no license file for the org) or VerifyLicense returns false (signature invalid / expired / tampered). Billing Sync requires a valid organization license to derive the CloudOrganizationId, so a missing or unverifiable license blocks connection creation. Maps to HTTP 400.
Source
Thrown at src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs:205
}
return type switch
{
OrganizationConnectionType.Scim => await _currentContext.ManageScim(organizationId.Value),
_ => await _currentContext.OrganizationOwner(organizationId.Value),
};
}
private async Task ValidateBillingSyncConfig(OrganizationConnectionRequestModel<BillingSyncConfig> typedModel)
{
if (!_globalSettings.SelfHosted)
{
throw new BadRequestException($"Cannot create a {typedModel.Type} connection outside of a self-hosted instance.");
}
var license = await _licensingService.ReadOrganizationLicenseAsync(typedModel.OrganizationId);
if (license == null || !_licensingService.VerifyLicense(license))
{
throw new BadRequestException("Cannot verify license file.");
}
typedModel.ParsedConfig.CloudOrganizationId = license.Id;
}
private async Task<OrganizationConnectionResponseModel> CreateOrUpdateOrganizationConnectionAsync<T>(
Guid? organizationConnectionId,
OrganizationConnectionRequestModel model,
Func<OrganizationConnectionRequestModel<T>, Task>? validateAction = null)
where T : IConnectionConfig
{
var typedModel = new OrganizationConnectionRequestModel<T>(model);
if (validateAction != null)
{
await validateAction(typedModel);
}
var data = typedModel.ToData(organizationConnectionId);
var connection = organizationConnectionId.HasValueView on GitHub (pinned to e93b962371)
Solutions
- Generate and install a valid organization license (from the cloud org owner portal) onto the self-hosted instance.
- Renew an expired license and reinstall the new file.
- Verify the server's system clock is correct (NTP) so license expiry/signature checks pass.
- Confirm the licensing public key configured on the server matches the key that signed the license.
- Check that ReadOrganizationLicenseAsync can locate the license file path for the org.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure a valid org license is installed before creating BillingSync
var license = await licensingService.ReadOrganizationLicenseAsync(orgId);
if (license == null) throw new InvalidOperationException("No organization license installed.");
if (!licensingService.VerifyLicense(license)) throw new InvalidOperationException("License failed verification."); Try / catch
try { await client.PostAsync("organizations/connections", billingSyncBody); }
catch (ApiException ex) when (ex.Message.Contains("Cannot verify license")) {
// prompt admin to install/renew the org license, then retry
} Prevention
- Install a current, signed organization license on the self-hosted instance first.
- Keep the server clock synced via NTP so expiry/signature checks pass.
- Confirm the server's configured licensing public key matches the license signer.
- Renew licenses before expiry.
When it happens
Trigger: POST/PUT a CloudBillingSync connection when the organization has no installed license file on the self-hosted server, or the installed license is expired, revoked, signed by an untrusted key, or corrupted.
Common situations: License never installed on the self-hosted instance; license expired and not renewed; server clock skew causing signature/expiry validation failure; license file corrupted during transfer; wrong signing key configured on the server.
Related errors
- Cannot create a {typedModel.Type} connection outside of a se
- Unable to get Cloud Billing Sync connection
- You do not have permission to create a connection of type {m
- The requested organization already has a connection of type
- Unknown Organization connection Type: {model.Type}
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/7553491bf65637c2.
Report an issue: GitHub.