bitwarden/server · error · BadRequestException
User verification failed.
Error message
User verification failed.
What it means
Thrown (HTTP 400, model-state error under an empty key) by POST /devices/update-trust when _userService.VerifySecretAsync(user, model.Secret) returns false. A deliberate 2-second Task.Delay is awaited first to throttle brute-force attempts on the master password / OTP before updating device trust.
Source
Thrown at src/Api/Controllers/DevicesController.cs:178
}
return new ProtectedDeviceResponseModel(device);
}
[HttpPost("update-trust")]
public async Task PostUpdateTrust([FromBody] UpdateDevicesTrustRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}
if (!await _userService.VerifySecretAsync(user, model.Secret))
{
await Task.Delay(2000);
throw new BadRequestException(string.Empty, "User verification failed.");
}
await _deviceService.UpdateDevicesTrustAsync(
_currentContext.DeviceIdentifier,
user.Id,
model.CurrentDevice,
model.OtherDevices ?? Enumerable.Empty<OtherDeviceKeysUpdateRequestModel>());
}
[HttpPost("untrust")]
public async Task PostUntrust([FromBody] UntrustDevicesRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}View on GitHub (pinned to e93b962371)
Solutions
- Re-enter the correct master password or current OTP code.
- If the password was recently changed, ensure the client has refreshed credentials before retrying.
- Use account recovery if the master password is forgotten.
Defensive patterns
Strategy: try-catch
Try / catch
// Secret verification cannot be safely pre-checked client-side; wrap the call and re-prompt on failure.
try {
await post('/devices/update-trust', { secret, ... });
} catch (e) {
if (e.isBadRequest && e.modelState?.['']?.includes('User verification failed.')) {
showSecretPrompt('Incorrect master password or OTP. Try again.');
} else { throw e; }
} Prevention
- Re-type the master password rather than retrying a stale cached value.
- Sync the client to the current password before secret-verified device operations.
- Avoid repeated blind retries due to the built-in throttle.
When it happens
Trigger: Incorrect master password supplied; incorrect OTP code; the client is hashing against stale KDF parameters after a parameter change; secret typed for a different account.
Common situations: Caps-lock or wrong keyboard layout; stale client session using an old password after a password change; wrong account; clock drift invalidating TOTP.
Related errors
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/22d12d21778a7ef4.
Report an issue: GitHub.