{"record":{"id":"d2607e5e8cba3930","repo":"googleapis/mcp-toolbox","slug":"failed-to-encode-prm-response","errorCode":null,"errorMessage":"Failed to encode PRM response","messagePattern":"Failed to encode PRM response","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"internal/server/mcp.go","lineNumber":913,"sourceCode":"\tfor _, authSvc := range s.PrimitiveMgr.AuthServices() {\n\t\tif mSvc, ok := authSvc.(auth.MCPAuthService); ok && mSvc.IsMCPEnabled() {\n\t\t\tserver = mSvc.GetAuthorizationServer()\n\t\t\tscopes = mSvc.GetScopesRequired()\n\t\t\tbreak\n\t\t}\n\t}\n\n\tres := prmResponse{\n\t\tResource:               s.toolboxUrl,\n\t\tAuthorizationServers:   []string{server},\n\t\tScopesSupported:        scopes,\n\t\tBearerMethodsSupported: []string{\"header\"},\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tif err := json.NewEncoder(w).Encode(res); err != nil {\n\t\ts.logger.ErrorContext(r.Context(), fmt.Sprintf(\"Failed to encode PRM response: %v\", err))\n\t\thttp.Error(w, \"Failed to encode PRM response\", http.StatusInternalServerError)\n\t}\n}\n","sourceCodeStart":895,"sourceCodeEnd":916,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/mcp.go#L895-L916","documentation":"In the Protected Resource Metadata (PRM) HTTP handler, after building the JSON response the server tries to json.Encode it into the http.ResponseWriter. If writing to the response stream fails (client disconnected, broken pipe, TLS/network error mid-response), Encode returns an error and the server logs \"Failed to encode PRM response\" and attempts a 500 response.","triggerScenarios":"A client closes the connection or times out while the PRM endpoint (e.g. GET /.well-known/oauth-protected-resource) is streaming the JSON body; the underlying TCP connection errors during Write.","commonSituations":"Aggressive client timeouts in OAuth discovery flows; load balancers closing idle keep-alive connections; client cancels the request right after headers are sent; proxy buffering limits.","solutions":["Retry the discovery request from the client; this is usually a transient transport failure","Increase the client/proxy read timeout so the PRM response can complete","Check server logs for the underlying encoding error detail to confirm client disconnect vs server issue","Verify network path (LB, ingress) isn't terminating responses early"],"exampleFix":"// before (client side)\nconst res = await fetch(url);\n// after (client side, with timeout headroom)\nconst res = await fetch(url, { signal: AbortSignal.timeout(30000) });","handlingStrategy":"retry","validationCode":"// client: check connectivity before fetching PRM\nconst url = new URL(baseUrl + '/.well-known/oauth-protected-resource');\nif (!['http:', 'https:'].includes(url.protocol)) throw new Error('bad base URL');","typeGuard":null,"tryCatchPattern":"// client side\ntry {\n  const res = await fetch(prmUrl, { signal: AbortSignal.timeout(30000) });\n  if (!res.ok) throw new Error(`PRM request failed: ${res.status}`);\n  const prm = await res.json();\n} catch (e) {\n  if (e.name === 'TimeoutError' || e.name === 'AbortError') retryFetch(prmUrl);\n  else throw e;\n}","preventionTips":["Set client timeouts generously for OAuth discovery endpoints","Avoid closing connections immediately after issuing the discovery request","Configure LBs/proxies to keep the connection alive until the small JSON body is delivered","Monitor server logs for repeated PRM encode errors indicating client/proxy misbehavior"],"tags":["http","json","oauth","network","broken-pipe"],"backgroundTag":"response-write-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}