ory/hydra · warning
err.Error()
Error message
err.Error()
What it means
In the `hydra perform authorization-code` CLI's loginGET handler, the raw login request body returned by the Hydra Admin API (GetOAuth2LoginRequest) is pretty-printed via prettyJSON before being rendered into the tokenUserLogin HTML template. If reading/pretty-printing that JSON body fails, the CLI responds with HTTP 500 and err.Error() — the prettyJSON/JSON-decoding error message (e.g. "unexpected EOF", "invalid character ..."). The displayed text is the underlying parse error, not a structured error type.
Source
Thrown at cmd/cmd_perform_authorization_code.go:382
defer raw.Body.Close() //nolint:errcheck
if rt.skip && req.GetSkip() {
req, res, err := rt.cl.OAuth2API.AcceptOAuth2LoginRequest(r.Context()).
LoginChallenge(req.Challenge).
AcceptOAuth2LoginRequest(openapi.AcceptOAuth2LoginRequest{Subject: req.Subject}).
Execute()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer res.Body.Close() //nolint:errcheck
http.Redirect(w, r, req.RedirectTo, http.StatusFound)
return
}
pretty, err := prettyJSON(raw.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = tokenUserLogin.Execute(w, struct {
LoginChallenge string
Skip bool
SessionID string
Raw string
}{
LoginChallenge: req.Challenge,
Skip: req.GetSkip(),
SessionID: req.GetSessionId(),
Raw: pretty,
})
}
func (rt *router) loginPOST(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)View on GitHub (pinned to 4174065ffb)
Solutions
- Check the CLI logs/curl the admin endpoint directly to see the actual response body; fix the upstream response (correct endpoint URL).
- Ensure the admin URL is the Hydra admin port (e.g. :4445) and not a public port or UI behind an HTML-serving proxy.
- Retry the flow; if it is a flaky proxy/timeouts, disable intermediaries or increase timeouts.
- In code, close the body only after prettyJSON has read it and log the body when parsing fails for diagnosis.
Example fix
// before
defer raw.Body.Close()
pretty, err := prettyJSON(raw.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
// after
pretty, rawBody, err := prettyJSON(raw.Body)
if err != nil {
log.Printf("failed to parse login response %q: %v", rawBody, err)
http.Error(w, "failed to render login page", http.StatusInternalServerError)
return
}
defer raw.Body.Close() Defensive patterns
Strategy: try-catch
Validate before calling
// verify the admin endpoint returns JSON before driving the CLI flow curl -s -f "$ADMIN_URL/admin/oauth2/auth/requests/login?login_challenge=..." | jq . >/dev/null || echo "non-JSON response"
Try / catch
if pretty, err := prettyJSON(raw.Body); err != nil {
log.Printf("prettyJSON failed: %v", err)
http.Error(w, "failed to render login page", http.StatusInternalServerError)
return
} Prevention
- Point the CLI at the Hydra admin endpoint (:4445) directly, not through HTML-serving proxies.
- Log the raw response body whenever JSON parsing fails.
- Read/close response bodies exactly once and check truncation (io.ReadAll error) before parsing.
When it happens
Trigger: The admin API response body was truncated/corrupted (connection closed mid-response, proxy buffering issues), the body was already consumed or closed before prettyJSON read it, or the response is not valid JSON (HTML error page from an intermediary).
Common situations: Running the CLI behind a corporate proxy that rewrites responses; Hydra endpoint returning an error page instead of JSON; Go HTTP client timeouts cutting the body; raw.Body read twice (once for parse, once for pretty).
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- unable to decode JSON: %w
- expected X-Forwarded-Proto header to be https but got: %s
- Failed to encode request body: %s
- command expects one argument which is the path to the output
- cookiex: payload must be a flat JSON object with string valu
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/a804d86c26e3a093.
Report an issue: GitHub.