How to Fix the Socket Hang Up Error in Node.js
Work out whether a reused connection, your own timer or the server closed it, with Node.js code for each fix.
Updated
TL;DR
Error: socket hang up means Node.js saw the connection close before any response arrived: the server or a proxy ended it, or your code destroyed the request. When a safe-to-repeat request fails this way on a reused keep-alive connection, resending it on a new connection fixes it.
What socket hang up looks like in each client
Each row is a connection that closed before any reply; the TLS row closed during the handshake.
| Where | What you see |
|---|---|
| Node.js http and https (code: 'ECONNRESET' printed below) | Error: socket hang up |
| Node.js fetch() and its cause (code UND_ERR_SOCKET) | TypeError: fetch failed ... [cause]: SocketError: other side closed |
| axios in Node.js, as console.log prints it | AxiosError: socket hang up |
| Node.js https, closed during the TLS handshake | Error: Client network socket disconnected before secure TLS connection was established |
| npm 11 | npm error network request to https://registry.npmjs.org/left-pad failed, reason: socket hang up |
| Python requests | requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response')) |
| curl | curl: (52) Empty reply from server |
Why this happens
The other end, or your own code, closed the connection before any reply came back.
Node.js raises it when the socket ends while the request still has no response. A common trigger is a keep-alive connection that the server closes just as your client sends the next request on it.
Diagnose your socket hang up first
Each check ties the early close to one cause, so you change only that part.
Check the URL your code calls; if it pairs http:// with port 443 or another HTTPS port, a TLS server got plain HTTP and closed.
Note when it fails; if only the first request after an idle pause fails, the server closed that idle connection as you reused it.
Search your code for req.destroy() or abort() in a timeout handler; if it fires before the reply, your own code hung up.
Time the failing request; if it always ends after the same number of seconds, a fixed timer in the server or a proxy closed it.
Behind a proxy, rerun with curl -x and an https:// URL; Proxy CONNECT aborted means the proxy closed, Empty reply from server points past it.
Solutions ranked by effectiveness
Start with the retry, the usual fix; the next two cover your own timeouts and the servers you run.
- Most common fix
Retry requests that hung up on reused connections
Applies when the hang up hit a connection kept open from an earlier request. Node.js documents checking req.reusedSocket; resend a GET once, and treat a hang up on a fresh connection as a different cause.
const https = require("node:https"); const agent = new https.Agent({ keepAlive: true }); function get(url, retried = false) { const req = https.get(url, { agent }, (res) => res.resume().on("end", () => console.log(res.statusCode))); req.on("error", (err) => { if (req.reusedSocket && err.message === "socket hang up" && !retried) return get(url, true); console.log("failed:", err.message); }); } get("https://example.com/"); setTimeout(() => get("https://example.com/"), 3000); - Check next
Stop your own timeout from ending requests
Applies when the hang up comes from your own timer. Called without an error, destroy() reports socket hang up, so set the limit above the endpoint's real time and pass an Error naming it.
const https = require("node:https"); const started = Date.now(); const req = https.get("https://example.com/report", { timeout: 60000 }, (res) => { res.resume().on("end", () => console.log(res.statusCode, "after", Date.now() - started, "ms")); }); req.on("timeout", () => req.destroy(new Error("no data for 60 s, gave up"))); req.on("error", (err) => console.log("failed after", Date.now() - started, "ms:", err.message)); - Site owners
Reply with an error instead of crashing
Applies when hang ups match your Node.js server restarting. An async handler that throws takes down a plain http server and every request in flight; catch the error and answer 500.
const http = require("node:http"); async function handle(req, res) { throw new Error("database down"); } http.createServer((req, res) => { handle(req, res).catch((err) => { console.error(err); if (res.headersSent) return res.destroy(err); res.writeHead(500).end("Internal Server Error\n"); }); }).listen(8080);
Stop the socket hang up from coming back
Habits for client code and the servers you run, so one early close stays a logged, recoverable error.
Attach an error listener to every request; without one, a single hang up stops your whole Node.js process.
Move Express 4 apps to Express 5, which passes errors from async handlers to your error middleware.
On Gunicorn, keep --timeout above your slowest request; by default it kills workers silent for 30 seconds.
Keep each base URL's scheme and port in one setting, so http:// never meets a port that expects HTTPS.
Related errors
Learn more
FAQ
Your proxy traffic, hour by hour
Geonode's Statistics section shows hourly usage trends, so you can spot your peak hours.


