ory/hydra · error
Failed to read response: %s
Error message
Failed to read response: %s
What it means
Returned when reading the response body of the admin device-accept call fails. The body is read through io.LimitReader(res.Body, 1<<20) (1 MiB cap); io.ReadAll errors on premature connection close, chunked-encoding corruption, or read timeouts. The handler responds with a 500.
Source
Thrown at cmd/cmd_perform_device_flow.go:224
http.Error(w, fmt.Sprintf("Failed to create request: %s", err), http.StatusInternalServerError)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
hc := cfg.HTTPClient
if hc == nil {
hc = http.DefaultClient
}
res, err := hc.Do(req)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to accept user code request: %s", err), http.StatusInternalServerError)
return
}
defer res.Body.Close() //nolint:errcheck
raw, err := io.ReadAll(io.LimitReader(res.Body, 1<<20))
if err != nil {
http.Error(w, fmt.Sprintf("Failed to read response: %s", err), http.StatusInternalServerError)
return
}
if res.StatusCode != http.StatusOK {
http.Error(w, fmt.Sprintf("Failed to accept user code request: %s", raw), http.StatusInternalServerError)
return
}
var accepted struct {
RedirectTo string `json:"redirect_to"`
}
if err := json.Unmarshal(raw, &accepted); err != nil || accepted.RedirectTo == "" {
http.Error(w, "Malformed response from the accept endpoint", http.StatusInternalServerError)
return
}
http.Redirect(w, r, accepted.RedirectTo, http.StatusSeeOther)
}
func (s *deviceSrv) GETdone(w http.ResponseWriter, r *http.Request) {View on GitHub (pinned to 4174065ffb)
Solutions
- Retry the whole accept request once on read failure — the error is transient and the PUT is idempotent for the same challenge.
- Check proxy/load-balancer timeout settings between the CLI and Hydra admin and raise read timeouts.
- Inspect Hydra admin logs at the same timestamp for a panic or early exit producing a truncated response.
Example fix
// before
raw, err := io.ReadAll(io.LimitReader(res.Body, 1<<20))
if err != nil {
http.Error(w, fmt.Sprintf("Failed to read response: %s", err), http.StatusInternalServerError)
return
}
// after
raw, err := io.ReadAll(io.LimitReader(res.Body, 1<<20))
if err != nil {
logger.Errorf("reading admin response failed: %v", err)
http.Error(w, "Truncated response from admin endpoint", http.StatusBadGateway)
return
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-check not directly possible; mitigate by bounding the read and checking status early.
if res.StatusCode >= 500 {
return fmt.Errorf("admin server error %d, body likely truncated/empty", res.StatusCode)
} Try / catch
raw, err := io.ReadAll(io.LimitReader(res.Body, 1<<20))
if err != nil {
// retry the whole request once — read errors are usually transient
if res2, rerr := hc.Do(req.Clone(ctx)); rerr == nil {
res, raw, err = res2, nil, nil
raw, err = io.ReadAll(io.LimitReader(res.Body, 1<<20))
}
if err != nil {
http.Error(w, "truncated admin response", http.StatusBadGateway)
return
}
} Prevention
- Raise proxy/LB read timeouts between client and Hydra admin
- Retry the entire idempotent PUT on read failure
- Keep the LimitReader bound so a hostile body can't exhaust memory
- Correlate with admin-side logs when truncation recurs
When it happens
Trigger: io.ReadAll(io.LimitReader(res.Body, 1<<20)) at cmd/cmd_perform_device_flow.go:224 returns an error — the Hydra admin connection dropped mid-response, a proxy terminated the chunked body, or a keep-alive/timeout cut the read short.
Common situations: Flaky networks between CLI and admin API; reverse proxies (nginx/traefik) with aggressive timeouts killing long responses; HTTP/1.0 style closes; running behind a load balancer that resets idle connections.
Related errors
- unable to read body
- expected status code 200 but got %d when requesting %s
- Failed to accept user code request: %s
- errKeyNotFound
- DNS lookup timed out
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/f9c071e6d5c12d29.
Report an issue: GitHub.