bitwarden/server · error · Exception

No license to generate.

Error message

No license to generate.

What it means

Thrown in the GenerateLicense action when neither a valid user nor a valid organization was resolved from the submitted model. The code checks model.UserId and model.OrganizationId, loads the respective entity, and if both are null/unset (and ModelState is otherwise valid), this else-branch fires. It indicates the form was submitted with neither a user ID nor an organization ID.

Source

Thrown at src/Admin/Controllers/ToolsController.cs:337

            var license = await _getCloudOrganizationLicenseQuery.GetLicenseAsync(organization,
                model.InstallationId.Value, model.Version);
            var ms = new MemoryStream();
            await JsonSerializer.SerializeAsync(ms, license, JsonHelpers.Indented);
            ms.Seek(0, SeekOrigin.Begin);
            return File(ms, "text/plain", "bitwarden_organization_license.json");
        }
        else if (user != null)
        {
            var license = await _userService.GenerateLicenseAsync(user, null, model.Version);
            var ms = new MemoryStream();
            ms.Seek(0, SeekOrigin.Begin);
            await JsonSerializer.SerializeAsync(ms, license, JsonHelpers.Indented);
            ms.Seek(0, SeekOrigin.Begin);
            return File(ms, "text/plain", "bitwarden_premium_license.json");
        }
        else
        {
            throw new Exception("No license to generate.");
        }
    }
}

View on GitHub (pinned to e93b962371)

Solutions

  1. Ensure the license generation form has either a UserId or an OrganizationId filled before submission.
  2. Add server-side ModelState validation that at least one of UserId/OrganizationId is required (it appears ModelState may pass when both are null since they are optional fields).
  3. If calling the endpoint programmatically, always include one of the two IDs in the request body.
  4. Consider adding a [Required] attribute on a custom validation property to enforce mutual exclusivity and presence.

Example fix

// before: no validation for at-least-one
// after: add a model-level validation
if (!model.UserId.HasValue && !model.OrganizationId.HasValue)
{
    ModelState.AddModelError(string.Empty, "Either User Id or Organization Id is required.");
    return View(model);
}
Defensive patterns

Strategy: validation

Validate before calling

// Server-side: enforce at least one target before processing
if (!model.UserId.HasValue && !model.OrganizationId.HasValue)
{
    ModelState.AddModelError(string.Empty, "Either User Id or Organization Id is required.");
    return View(model);
}

Type guard

static bool HasLicenseTarget(LicenseModel model)
    => model.UserId.HasValue || model.OrganizationId.HasValue;

Prevention

When it happens

Trigger: An admin submits the license generation form without selecting either a user or an organization. This is typically unreachable in the normal UI flow because form validation should catch the empty state, but can be triggered by a direct API call or a client-side validation bypass.

Common situations: A direct HTTP POST to the GenerateLicense endpoint with an empty body or a body missing both UserId and OrganizationId. A browser extension or script that bypasses client-side validation. A UI bug that allows submission without selecting a target.

Related errors


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