Online Issue - ERR_CONNECTION_CLOSED
During the regular Thursday technical meeting, someone raised an online issue. There’s a table header filter on the web that reports error
ERR_CONNECTION_CLOSED
when selecting all values for a request, but returns 200 normally when selecting fewer values. Because the meaning ofERR_CONNECTION_CLOSED
wasn’t clear, the troubleshooting process took some detours. Here’s a summary.
ERR_CONNECTION_CLOSED
Chrome reports request errors but without status codes, so initially it wasn’t clear whether it was a server-side or browser-level error.
But generally, we start troubleshooting from the frontend.
Request Body Limit?
Phenomenologically, reducing parameter values returns 200, while more parameter values cause errors. So initially it was judged that it might be a request body size limit.
Therefore, I randomly constructed a longer array parameter and found that the backend returned information normally (though it reported illegal parameter errors), thus disproving the body size limit theory.
Header Length Limit?
Noticed another feature when errors occur - the current URL is passed in the request header, and when table header filtering operates, the URL also updates. So it might be a header length issue.
When errors occur, the request header is about 10KB. To confirm this, I customized a header field, filled it with values to reach 10KB length, and tested with a value that previously returned 200 normally. Found it still reported errors.
Therefore, it can be confirmed that it’s not a business-level error caused by some parameter value, but rather a request header length limitation.
Solution
Once the cause is found, the solution becomes clear
Increase container header length limit
- HTTP itself doesn’t limit req.header length, only individual containers have limits
Modify the request header to avoid passing overly large request headers. For example, here a long URL was being passed as a header parameter just for logging purposes. There’s no need to pass the complete URL parameter, so we ultimately decided to use a truncation solution - limit the maximum URL length. Also note that overly long URLs themselves are unreasonable because browsers also have URL length limitations.
Need to know that this error is caused by header length limitations, but if body length exceeds limits, this error can also occur.
Looking back at the error message ERR_CONNECTION_CLOSED, it makes sense now
HTTP connections are built on top of TCP connections. As above, when header length exceeds limits, the server directly closes that TCP connection. Whereas the so-called 500, 400 errors are just HTTP connection endings, but the TCP connection still exists. There’s a fundamental difference between the two.
Since it’s a connection, the request must have been normally sent to the server, but at the server container layer, it errored due to length limit exceedance.
node/–max-http-header-size
Problem solved. To reinforce understanding, here’s using node as an example to reproduce the issue
Node’s default header size limit is 8KB. So here I added a larger custom header item, requested the node server, and found the request errored. Restarted node with header上限 specified as 1500000, and found it returned 200.
// Start server
node --max-http-header-size 1500000 app.js
// JS custom header field information
xhr.setRequestHeader('...')
Summary
Generally, we’re used to judging backend errors based on Response Status, but for example, the above error doesn’t have a status, yet it’s indeed a server-side error.
Therefore, we need to have this awareness: server-side errors don’t necessarily have responseStatus.