{"record":{"id":"9db8c4051546f2b2","repo":"ory/hydra","slug":"server-error-9db8c4","errorCode":"server_error","errorMessage":"{\"error\":\"server_error\",\"error_description\":\"%s\"}","messagePattern":"\\{\"error\":\"server_error\",\"error_description\":\"%s\"\\}","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"fosite/authorize_error.go","lineNumber":30,"sourceCode":"\nfunc (f *Fosite) WriteAuthorizeError(ctx context.Context, rw http.ResponseWriter, ar AuthorizeRequester, err error) {\n\trw.Header().Set(\"Cache-Control\", \"no-store\")\n\trw.Header().Set(\"Pragma\", \"no-cache\")\n\n\tif f.ResponseModeHandler(ctx).ResponseModes().Has(ar.GetResponseMode()) {\n\t\tf.ResponseModeHandler(ctx).WriteAuthorizeError(ctx, rw, ar, err)\n\t\treturn\n\t}\n\n\trfcerr := ErrorToRFC6749Error(err).WithLegacyFormat(f.Config.GetUseLegacyErrorFormat(ctx)).WithExposeDebug(f.Config.GetSendDebugMessagesToClients(ctx)).WithLocalizer(f.Config.GetMessageCatalog(ctx), getLangFromRequester(ar))\n\tif !ar.IsRedirectURIValid() {\n\t\trw.Header().Set(\"Content-Type\", \"application/json;charset=UTF-8\")\n\n\t\tjs, err := json.Marshal(rfcerr)\n\t\tif err != nil {\n\t\t\tif f.Config.GetSendDebugMessagesToClients(ctx) {\n\t\t\t\terrorMessage := EscapeJSONString(err.Error())\n\t\t\t\thttp.Error(rw, fmt.Sprintf(`{\"error\":\"server_error\",\"error_description\":\"%s\"}`, errorMessage), http.StatusInternalServerError)\n\t\t\t} else {\n\t\t\t\thttp.Error(rw, `{\"error\":\"server_error\"}`, http.StatusInternalServerError)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\trw.WriteHeader(rfcerr.CodeField)\n\t\t_, _ = rw.Write(js)\n\t\treturn\n\t}\n\n\tredirectURI := ar.GetRedirectURI()\n\n\t// The endpoint URI MUST NOT include a fragment component.\n\tredirectURI.Fragment = \"\"\n\n\terrors := rfcerr.ToValues()\n\terrors.Set(\"state\", ar.GetState())","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/fosite/authorize_error.go#L12-L48","documentation":"In fosite's WriteAuthorizeError, when the error is not meant to redirect back to the client (e.g. invalid client or no redirect URI registered), fosite writes the error as a JSON body. If json.Marshal(rfcerr) then fails, and SendDebugMessagesToClients is enabled, it emits {\"error\":\"server_error\",\"error_description\":\"<marshal error>\"} with status 500 — the same last-resort path as access_error.go, in the authorize endpoint.","triggerScenarios":"WriteAuthorizeError takes the JSON branch (no valid redirect possible) and json.Marshal(rfcerr) fails at fosite/authorize_error.go:30 — custom error/args values attached by an authorize handler containing channels, funcs, or cyclic references; also triggered when the client's redirect URI is invalid so fosite must render JSON instead of redirecting.","commonSituations":"Authorization requests with unregistered client_id or disallowed redirect_uri (forces the JSON branch) combined with custom handlers that stash unserializable data on the error; debug mode enabled; custom storage returning errors wrapped with unserializable context.","solutions":["Fix the root cause of the authorize error first (valid client_id and redirect_uri registration) so the redirect branch is used instead of JSON rendering.","Audit custom authorize handlers and storage errors for non-serializable values attached to fosite errors.","Disable SendDebugMessagesToClients in production so marshal failures return the generic {\"error\":\"server_error\"} body.","Add a regression test marshaling your custom error type through WriteAuthorizeError."],"exampleFix":"// before\nreturn errors.Wrapf(err, \"db fail: %v\", conn) // conn may be unserializable when fosite re-wraps\n// after\nreturn fosite.ErrServerError.WithHint(\"storage unavailable\")\n// and register redirect URIs so errors redirect instead of JSON-rendering:\n// client.RedirectURIs = []string{\"https://app.example.com/callback\"}","handlingStrategy":"try-catch","validationCode":"// Verify client registration prevents the JSON branch (always provide a valid redirect):\nif len(client.GetRedirectURIs()) == 0 {\n\treturn errors.New(\"client has no registered redirect URIs — authorize errors will JSON-render\")\n}","typeGuard":"func authorizeErrorRedirectable(err *fosite.RFC6749Error) bool {\n\treturn err.ReasonCode != fosite.ErrInvalidRequestURI.ReasonCode && len(err.Hint) > 0\n}","tryCatchPattern":"// Ensure errors redirect where possible; wrap WriteAuthorizeError to log first:\nfunc writeAuthorizeError(ctx context.Context, f *fosite.Fosite, rw http.ResponseWriter, ar fosite.AccessRequester, err error) {\n\tlog.Printf(\"authorize error: %v\", err)\n\tf.WriteAuthorizeError(ctx, rw, ar, err)\n}","preventionTips":["Register valid redirect_uri values for all clients so errors use the redirect branch","Only attach string-safe hints/descriptions to fosite errors","Disable SendDebugMessagesToClients in production","Test your custom authorize handlers end-to-end with invalid clients to exercise the JSON branch"],"tags":["oauth2","fosite","authorize"],"backgroundTag":"json-marshal-failed","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}