-
Notifications
You must be signed in to change notification settings - Fork 198
Recovery middleware catches http.ErrAbortHandler, corrupting proxy responses #4064
Description
Bug Description
The recovery middleware (pkg/recovery/recovery.go) catches all panics
indiscriminately, including http.ErrAbortHandler. This is a sentinel panic
value that Go's httputil.ReverseProxy uses intentionally when a streaming
response breaks mid-copy (reverseproxy.go:612). Go's HTTP server has built-in
handling for this: catch it silently, close the connection, move on.
By intercepting ErrAbortHandler, the recovery middleware:
- Logs a noisy stack trace for something that isn't a bug
- Tries to write
http.Error(w, "Internal Server Error", 500)to an
already-in-flight response, corrupting it - Prevents Go's HTTP server from cleanly aborting the connection
Steps to Reproduce
- Run any MCP server through ToolHive's transparent proxy
- Have a client disconnect or timeout mid-stream (e.g., Claude Code closing
an SSE connection) - Observe
Panic recovered: net/http: abort HandlerERROR log entries with
full stack traces originating fromreverseproxy.go:612
Expected Behavior
http.ErrAbortHandler should propagate to Go's HTTP server, which handles it
silently by closing the connection. No log output, no attempted 500 response.
Actual Behavior
Every aborted streaming response produces an ERROR-level log entry with a full
stack trace, and the middleware attempts to write a 500 response to a connection
that is already mid-response.
Environment
- ToolHive v0.11.1 (also reproducible on current main)
- OS: macOS (the code path is platform-independent, so likely affects Linux too)
- Affects all servers using the transparent proxy