{"record":{"id":"b83d973891a1de54","repo":"jaegertracing/jaeger","slug":"failed-writing-http-response-w","errorCode":null,"errorMessage":"failed writing HTTP response: %w","messagePattern":"failed writing HTTP response: %w","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"cmd/jaeger/internal/extension/jaegerquery/internal/http_handler.go","lineNumber":421,"sourceCode":"\thttp.Error(w, string(resp), statusCode)\n\treturn true\n}\n\nfunc (aH *APIHandler) writeJSON(w http.ResponseWriter, r *http.Request, response any) {\n\tprettyPrintValue := r.URL.Query().Get(prettyPrintParam)\n\tprettyPrint := prettyPrintValue != \"\" && prettyPrintValue != \"false\"\n\n\tvar marshal jsonMarshaler\n\tswitch response.(type) {\n\tcase proto.Message:\n\t\tmarshal = newProtoJSONMarshaler(prettyPrint)\n\tdefault:\n\t\tmarshal = newStructJSONMarshaler(prettyPrint)\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tif err := marshal(w, response); err != nil {\n\t\taH.handleError(w, fmt.Errorf(\"failed writing HTTP response: %w\", err), http.StatusInternalServerError)\n\t}\n}\n\nfunc (aH *APIHandler) getQualityMetrics(w http.ResponseWriter, r *http.Request) {\n\tdata := qualitymetrics.GetSampleData()\n\taH.writeJSON(w, r, &data)\n}\n","sourceCodeStart":403,"sourceCodeEnd":429,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/jaeger/internal/extension/jaegerquery/internal/http_handler.go#L403-L429","documentation":"writeJSON serializes an API response and writes it to the http.ResponseWriter; if the marshal-and-write step fails, it responds 500 with \"failed writing HTTP response\". The library throws it so handler authors and operators can distinguish response-serialization/IO failures from query failures.","triggerScenarios":"Any HTTP query endpoint (transformOTLP, /api/dependencies, deep dependencies, metrics, getTrace, archiveTrace) where the marshaled response cannot be written to the client, or a non-standard marshaler fails while encoding.","commonSituations":"Client disconnected mid-response (broken pipe) on a large trace or long dependencies query; reverse proxy closing the connection; response body larger than an intermediary's limits.","solutions":["Check server/proxy logs for the wrapped cause (e.g. broken pipe, connection reset) — most cases are a client-side disconnect, not a Jaeger bug.","Retry the query with a smaller time range or limit to reduce the response size.","If persistent, inspect proxies/load balancers for idle-timeout or body-size limits between the client and jaeger-query."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := http.Get(url)\nif err != nil { return err }\ndefer resp.Body.Close()\nif resp.StatusCode == http.StatusInternalServerError {\n    body, _ := io.ReadAll(resp.Body)\n    log.Printf(\"query endpoint failed writing response: %s\", body) // check wrapped cause in server logs\n}","preventionTips":["Keep reverse-proxy timeouts and body-size limits larger than your largest expected query responses.","Bound query time ranges/limits so responses stay small.","Treat sporadic 500s on large responses as client disconnects and retry with narrower queries."],"tags":["http","json","response-writing"],"backgroundTag":"broken-pipe-response-write","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}