bitwarden/server · error · BadRequestException
Please provide a device type
Error message
Please provide a device type
What it means
Thrown by POST /devices/lost-trust when the device identifier is present but the device type is null in the request context. The endpoint logs a trust-loss event that includes the device type, so it refuses to proceed without it. Device type also comes from the device token claims set at registration time.
Source
Thrown at src/Api/Controllers/DevicesController.cs:328
[HttpPost("lost-trust")]
public void PostLostTrust()
{
var userId = _currentContext.UserId.GetValueOrDefault();
if (userId == default)
{
throw new UnauthorizedAccessException();
}
var deviceId = _currentContext.DeviceIdentifier;
if (deviceId == null)
{
throw new BadRequestException("Please provide a device identifier");
}
var deviceType = _currentContext.DeviceType;
if (deviceType == null)
{
throw new BadRequestException("Please provide a device type");
}
_logger.LogError("User {id} has a device key, but didn't receive decryption keys for device {device} of type {deviceType}", userId,
deviceId, deviceType);
}
}
View on GitHub (pinned to e93b962371)
Solutions
- Re-register the device supplying a valid DeviceType so the device token includes the type claim.
- Ensure the client sends the DeviceType field when registering/reviving the device token.
- Refresh the access token after registration so the type claim is present.
Example fix
// before: device registered without a type, token has no device-type claim
//
// after: register with an explicit DeviceType (e.g. Mobile=0, Desktop=6, ...)
await deviceRepo.SaveAsync(new Device { Type = DeviceType.Android, Identifier = deviceId }); Defensive patterns
Strategy: validation
Validate before calling
// Confirm the device token carries a type before calling lost-trust
const type = await getDeviceTypeClaim(accessToken);
if (type == null) {
await reRegisterDeviceWithType(chosenDeviceType); // DeviceType.Android, etc.
return;
}
await devicesApi.postLostTrust(); Type guard
function hasDeviceType(claims) { return claims?.devicetype != null; } Try / catch
try {
await devicesApi.postLostTrust();
} catch (e) {
if (e.status === 400 && /device type/i.test(e.message)) {
await reRegisterDeviceWithType(currentDeviceType);
} else throw e;
} Prevention
- Always send a DeviceType when registering/refreshing a device token.
- Refresh the access token after registration so the type claim is present.
- Keep device tokens current; old tokens minted before the type claim was added will fail.
When it happens
Trigger: Calling POST /devices/lost-trust with a device token that carries an identifier claim but no device-type claim. The earlier DeviceIdentifier check passes, then the DeviceType null check fires.
Common situations: Device registered/registered-token minted before the device-type claim was added; a token forged or partially built in tests; an old client that registered a device without sending a DeviceType and is now using a token lacking that claim.
Related errors
- Please provide a device identifier
- Please provide an email and device identifier
- ExternalId cannot exceed 300 characters.
- ExternalId cannot exceed 300 characters.
- result.AsError.Message
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/f6bd5ae5341c27d1.
Report an issue: GitHub.