Node.js — ETIMEDOUT or socket hang up on outbound requests
Diagnose ETIMEDOUT by separating network reachability, firewall drops and missing client timeouts.
Symptoms
- Error: connect ETIMEDOUT 10.0.0.5:443
- Requests hang for a long time before failing
- socket hang up without a response
- A firewall silently drops packets so no error returns quickly
Possible causes
- The destination host is unreachable or its firewall drops packets
- No timeout is set on the socket or HTTP request
- A load balancer or security group blocks the port
- The target service is overloaded and stops accepting
Diagnosis steps
Test reachability at the network layer
ping -c 2 10.0.0.5 ; nc -vz 10.0.0.5 443Interpretation
Ping tests ICMP while nc tests the TCP port. A port that hangs in nc indicates a dropped packet rather than a refusal.
Set an explicit request timeout
node -e "const r=require('https').request({host,port,timeout:3000},res=>res.resume()); r.on('timeout',()=>{console.error('timeout');r.destroy()}); r.end()"Interpretation
A short timeout surfaces the problem quickly instead of leaving requests stuck.
Check security group and route tables
aws ec2 describe-security-groups --group-ids sg-xxxInterpretation
Blocked ports or missing routes explain timeouts when the host is otherwise reachable.
Root cause
Packets to the destination were dropped rather than refused, so the client waited until its timeout expired. The cause is network reachability, firewall policy or an overloaded peer, compounded by missing client timeouts.
Fix
Open the required ports and routes, ensure the target service accepts connections, and always set connect and request timeouts so failures are fast and actionable.
Verify the fix
Retry the request and confirm it connects within the timeout, and confirm the firewall rules now permit the traffic from the client subnet.
Symptom walkthrough
Requests fail after a long wait with ETIMEDOUT or socket hang up, unlike ECONNREFUSED which fails immediately. The delay is the signal: the client sent packets and nothing came back, so a firewall or route dropped them. Because many HTTP clients inherit no timeout by default, the call can hang far longer than any user would tolerate.
Fix in practice
Verify network reachability and the specific port, then open the routes and security rules the traffic needs. Independently, always configure connect and total request timeouts so an unreachable peer fails quickly, and add retries with backoff only for operations that are safe to repeat.
Verification
Repeat the request and confirm it connects within the configured timeout, then confirm the security group or firewall now permits the source subnet on the target port. Recording the exact timeout that was configured also makes future regressions easier to spot.
Diagnostic commands
Check the behavior with commands like these:
ping -c 2 10.0.0.5 ; nc -vz 10.0.0.5 443
node -e "const r=require('https').request({host,port,timeout:3000},res=>res.resume()); r.on('timeout',()=>{console.error('timeout');r.destroy()}); r.end()"
aws ec2 describe-security-groups --group-ids sg-xxx