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

  1. Verify GlobalSettings:HibpApiKey is set to a valid, active HIBP API key (sign in at haveibeenpwned.com/api/key) and restart the server.
  2. 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.
  3. If self-hosted behind a proxy, confirm egress to https://haveibeenpwned.com/api/v3/ is allowed and not being throttled by an intermediary.
  4. 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

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


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