jaegertracing/jaeger · warning
failed writing HTTP response: %w
Error message
failed writing HTTP response: %w
What it means
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.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/http_handler.go:421
http.Error(w, string(resp), statusCode)
return true
}
func (aH *APIHandler) writeJSON(w http.ResponseWriter, r *http.Request, response any) {
prettyPrintValue := r.URL.Query().Get(prettyPrintParam)
prettyPrint := prettyPrintValue != "" && prettyPrintValue != "false"
var marshal jsonMarshaler
switch response.(type) {
case proto.Message:
marshal = newProtoJSONMarshaler(prettyPrint)
default:
marshal = newStructJSONMarshaler(prettyPrint)
}
w.Header().Set("Content-Type", "application/json")
if err := marshal(w, response); err != nil {
aH.handleError(w, fmt.Errorf("failed writing HTTP response: %w", err), http.StatusInternalServerError)
}
}
func (aH *APIHandler) getQualityMetrics(w http.ResponseWriter, r *http.Request) {
data := qualitymetrics.GetSampleData()
aH.writeJSON(w, r, &data)
}
View on GitHub (pinned to 806f444784)
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.
Defensive patterns
Strategy: try-catch
Try / catch
resp, err := http.Get(url)
if err != nil { return err }
defer resp.Body.Close()
if resp.StatusCode == http.StatusInternalServerError {
body, _ := io.ReadAll(resp.Body)
log.Printf("query endpoint failed writing response: %s", body) // check wrapped cause in server logs
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed marshalling HTTP response to JSON: %w
- access denied
- no http.RoundTripper provided
- bad request
- unmarshalling ElasticSearch documents failed
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/b83d973891a1de54.
Report an issue: GitHub.