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

  1. Check the CLI logs/curl the admin endpoint directly to see the actual response body; fix the upstream response (correct endpoint URL).
  2. Ensure the admin URL is the Hydra admin port (e.g. :4445) and not a public port or UI behind an HTML-serving proxy.
  3. Retry the flow; if it is a flaky proxy/timeouts, disable intermediaries or increase timeouts.
  4. 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

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


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/a804d86c26e3a093. Report an issue: GitHub.