ory/hydra · error

Failed to encode request body: %s

Error message

Failed to encode request body: %s

What it means

This error is returned by the POSTdevice handler in the CLI device-flow helper when json.Marshal fails to serialize the {"user_code": ...} payload that is PUT to the Hydra admin device-accept endpoint. json.Marshal on a map[string]string practically never fails (no channels, funcs, or unsupported types), so hitting this indicates a programming error rather than a runtime condition. It is surfaced to the client as a plain-text 500 via http.Error.

Source

Thrown at cmd/cmd_perform_device_flow.go:201

	if challenge == "" {
		http.Error(w, "device_challenge is required", http.StatusBadRequest)
		return
	}

	// Accept the user code with a hand-rolled request instead of the generated
	// client: other modules in this repository compile this package against the
	// released hydra-client-go/v2 module, which predates the device
	// authorization API.
	cfg := s.cl.GetConfig()
	if len(cfg.Servers) == 0 {
		http.Error(w, "No Hydra endpoint is configured", http.StatusInternalServerError)
		return
	}
	acceptURL := strings.TrimSuffix(cfg.Servers[0].URL, "/") +
		"/admin/oauth2/auth/requests/device/accept?device_challenge=" + url.QueryEscape(challenge)
	body, err := json.Marshal(map[string]string{"user_code": userCode})
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to encode request body: %s", err), http.StatusInternalServerError)
		return
	}
	req, err := http.NewRequestWithContext(r.Context(), http.MethodPut, acceptURL, bytes.NewReader(body))
	if err != nil {
		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

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Verify the marshaled value is only plain strings; if it must hold other types, use a typed struct with JSON tags instead of map[string]string.
  2. Log the underlying marshal error (it already appears in the 500 body) and inspect the value being marshaled.
  3. Keep the http.Error fallback so failures return 500 rather than panicking; no client-side fix is possible.

Example fix

// before
body, err := json.Marshal(map[string]string{"user_code": userCode})
// after
type acceptReq struct {
	UserCode string `json:"user_code"`
}
body, err := json.Marshal(acceptReq{UserCode: userCode})
Defensive patterns

Strategy: validation

Validate before calling

payload := map[string]string{"user_code": userCode}
if _, err := json.Marshal(payload); err != nil {
	return fmt.Errorf("payload unserializable: %w", err)
}

Type guard

func marshalable(v any) bool {
	_, err := json.Marshal(v)
	return err == nil
}

Try / catch

body, err := json.Marshal(payload)
if err != nil {
	log.Printf("marshal failed: %v", err)
	http.Error(w, "internal error", http.StatusInternalServerError)
	return
}

Prevention

When it happens

Trigger: json.Marshal(map[string]string{"user_code": userCode}) returns an error at cmd/cmd_perform_device_flow.go:201. With the current literal map of strings this cannot happen at runtime; it would only fail if the payload type were changed to include unsupported values (channels, funcs, cyclic structures) or a custom MarshalJSON returning an error.

Common situations: Practically never seen in production with this exact code. Developers refactoring the handler to send structured payloads (e.g. embedding a struct with unmarshalable fields, or passing context through the map) can introduce it. Custom user_code wrapper types with faulty MarshalJSON methods are the realistic path.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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