bitwarden/server · error · BadRequestException
Request failed. Status code: {0}
Error message
Request failed. Status code: {0} What it means
Thrown by the HIBP (HaveIBeenPwned) breach-lookup proxy when the upstream HIBP API returns a status code that is neither 200 (success), 404 (no breaches — mapped to an empty array), nor a retryable 429. The HIBP API key must be configured (_globalSettings.HibpApiKey); any other failure (auth, server error, or a second 429 after the single automatic retry) is wrapped into a 400 BadRequest that includes the upstream status code.
Source
Thrown at src/Api/Dirt/Controllers/HibpController.cs:90
return Content("[]", "application/json");
}
else if (response.StatusCode == HttpStatusCode.TooManyRequests && retry)
{
var delay = 2000;
if (response.Headers.Contains("retry-after"))
{
var vals = response.Headers.GetValues("retry-after");
if (vals.Any() && int.TryParse(vals.FirstOrDefault(), out var secDelay))
{
delay = (secDelay * 1000) + 200;
}
}
await Task.Delay(delay);
return await SendAsync(username, false);
}
else
{
throw new BadRequestException("Request failed. Status code: " + response.StatusCode);
}
}
private string GetClientId()
{
var userId = _userService.GetProperUserId(User).Value;
using (var sha256 = SHA256.Create())
{
var hash = sha256.ComputeHash(userId.ToByteArray());
return Convert.ToBase64String(hash);
}
}
}
View on GitHub (pinned to e93b962371)
Solutions
- Verify GlobalSettings:HibpApiKey is set to a valid, active HIBP API key (sign in at haveibeenpwned.com/api/key) and restart the server.
- Inspect the embedded status code in the 400 response body: 401/403 → fix the key; 429 → wait and reduce call frequency or upgrade the HIBP subscription tier; 5xx → HIBP is down, retry later.
- If self-hosted behind a proxy, confirm egress to https://haveibeenpwned.com/api/v3/ is allowed and not being throttled by an intermediary.
- For chronic 429s, add client-side caching/debouncing of breach lookups so repeated username checks don't each hit HIBP.
Example fix
// before: a single retry, then a hard 400 on the next non-success
// after (extend retry budget + distinguish auth errors):
else if (response.StatusCode == HttpStatusCode.Unauthorized ||
response.StatusCode == HttpStatusCode.Forbidden)
{
throw new BadRequestException("HIBP API key is invalid or unauthorized.");
}
else
{
throw new BadRequestException("Request failed. Status code: " + response.StatusCode);
} Defensive patterns
Strategy: retry
Validate before calling
// Before calling /hibp/breach, ensure the deployment has a key configured.
// (Server-side config check; client can't see it, so just be ready to retry/back off.)
if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("GlobalSettings__HibpApiKey")))
throw new InvalidOperationException("HIBP API key is not configured on the server."); Try / catch
// Client calling GET /hibp/breach
try { var breaches = await client.GetAsync($"/hibp/breach?username={username}"); }
catch (HttpRequestException ex) when (ex.Message.Contains("Status code"))
{
// Parse embedded status; 401/403 → key issue (alert ops), 429/5xx → back off and retry
if (ex.Message.Contains("429") || ex.Message.Contains("50")) await Task.Delay(backoff);
else throw;
} Prevention
- Keep the HIBP API key valid and monitored; alert on 401/403 in the response body.
- Cache breach results client-side to reduce call frequency and avoid 429s.
- Treat 5xx from HIBP as transient — retry with exponential backoff.
When it happens
Trigger: GET /hibp/breach?username=<user> when the HIBP v3 API responds 401 (bad/expired API key), 403 (key valid but blocked / wrong scope), 5xx (HIBP outage), or a second consecutive 429 after the built-in single retry has already run (retry=false on the recursive call).
Common situations: Self-hosted deployment where GlobalSettings:HibpApiKey is missing, expired, or revoked; HIBP rate limit exceeded beyond the one automatic retry (the key's per-minute quota is exhausted); transient HIBP 5xx during their incidents; network egress blocked so the HttpClient gets a non-success or the request itself faults upstream.
Related errors
- Invalid response from Slack.
- Invalid response from Teams.
- HaveIBeenPwned API key not set.
- Resource not found.
- Max file size is 500 MB.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/e1417dbbeb1d6d75.
Report an issue: GitHub.