{"record":{"id":"acb101980e2c35e4","repo":"ory/kratos","slug":"errnetworkfailure","errorCode":"ErrNetworkFailure","errorMessage":"ErrNetworkFailure wrapped: %s (network failure during HIBP range request)","messagePattern":"ErrNetworkFailure wrapped: (.+?) \\(network failure during HIBP range request\\)","errorType":"error_code","errorClass":"wrapped sentinel error","httpStatus":null,"severity":"warning","filePath":"selfservice/strategy/password/validator.go","lineNumber":134,"sourceCode":"\t\t\t\t\tgreatestLength = curr\n\t\t\t\t}\n\t\t\t\tlengths[i*len(b)+j] = curr\n\t\t\t}\n\t\t}\n\t}\n\treturn greatestLength\n}\n\nfunc (s *DefaultPasswordValidator) fetch(ctx context.Context, hpw []byte, apiDNSName string) (int64, error) {\n\tprefix := fmt.Sprintf(\"%X\", hpw)[0:5]\n\tloc := fmt.Sprintf(\"https://%s/range/%s\", apiDNSName, prefix)\n\treq, err := retryablehttp.NewRequestWithContext(ctx, \"GET\", loc, nil)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tres, err := s.reg.HTTPClient(ctx, httpx.ResilientClientWithConnectionTimeout(time.Second)).Do(req)\n\tif err != nil {\n\t\treturn 0, errors.Wrapf(ErrNetworkFailure, \"%s\", err)\n\t}\n\tdefer func() { _ = res.Body.Close() }()\n\n\tif res.StatusCode != http.StatusOK {\n\t\treturn 0, errors.Wrapf(ErrUnexpectedStatusCode, \"%d\", res.StatusCode)\n\t}\n\n\tvar thisCount int64\n\n\tsc := bufio.NewScanner(res.Body)\n\tfor sc.Scan() {\n\t\trow := sc.Text()\n\t\tresult := strings.Split(strings.TrimSpace(row), \":\")\n\n\t\t// We assume a count of 1. HIBP API sometimes responds without the\n\t\t// colon, so we just assume that the leak count is one.\n\t\t//\n\t\t// See https://github.com/ory/kratos/issues/2145","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/password/validator.go#L116-L152","documentation":"The password validator checks leaked passwords via the HaveIBeenPwned range API. fetch performs the HTTP GET with a resilient HTTP client; if the request itself fails (connection error, timeout, DNS failure), the error is wrapped in ErrNetworkFailure with the underlying cause. This keeps the failure classifiable and subject to ignore_network_errors.","triggerScenarios":"Calling fetch (via validate) when retryablehttp request execution fails: api.pwnedpasswords.com unreachable, network outage, connection timeout (1s connection timeout), or proxy misconfiguration.","commonSituations":"Egress firewall blocking api.pwnedpasswords.com, DNS failures in restricted clusters, HIBP outages/rate limiting at connection level, or missing outbound internet access in air-gapped deployments.","solutions":["Set ignore_network_errors: true in the password HIBP config so registration proceeds when HIBP is unreachable.","Verify outbound connectivity: curl https://api.pwnedpasswords.com/range/AAAAA from the server.","Check proxy/firewall rules and allow egress to api.pwnedpasswords.com (HTTPS/443).","Inspect the wrapped cause for the exact transport error (timeout vs refused vs DNS)."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"conn, err := net.DialTimeout(\"tcp\", \"api.pwnedpasswords.com:443\", 2*time.Second)\nif err != nil { /* egress to HIBP is blocked; enable ignore_network_errors */ }","typeGuard":null,"tryCatchPattern":"if errors.Is(err, strategy.ErrNetworkFailure) {\n  if cfg.IgnoreNetworkErrors { return allowed /* skip HIBP check */ }\n  return err\n}","preventionTips":["Set ignore_network_errors: true for HIBP in availability-sensitive flows.","Allow egress to api.pwnedpasswords.com in firewalls/proxies.","Monitor HIBP reachability from the cluster.","Keep the built-in prefix hash cache effective (long-lived instances)."],"tags":["network","hibp","password","http-client"],"backgroundTag":"network-request-failed","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}