Why localhost TCP connections sometimes throw ECONNRESET — and how to fix it
A developer traces an intermittent ECONNRESET between two local services down to a subtle TCP behavior: when a server closes a socket while unread data is still sitting in its receive buffer, the kernel sends an RST rather than a clean FIN. A minimal reproduction shows that as long as the client never sends bytes, the transfer completes cleanly; the moment the client writes even a single byte that the server ignores, closing the socket on the server side triggers a reset that the client sees mid-read, sometimes after hundreds of thousands of bytes have already been delivered.
The real-world incident behind the post involved nginx proxying to gunicorn-backed Flask. Nginx split the HTTP request across two writev calls (headers, then body), and when the application didn’t read the body before responding and closing, the unread bytes in the kernel buffer caused an RST back to nginx. Because timing depended on cloud routers, firewalls, and parallel requests, the root cause took significant effort to isolate.
The fix was to force the application to drain the request body before responding, eliminating the pending data at close time. The author notes the obvious tradeoff: blindly reading arbitrary POST bodies invites DoS, so pairing the drain with nginx’s client_max_body_size is the safer pattern.
Read the full article
Continue reading at Hacker News →This is an AI-generated summary. Read the original for the full story.