← Debugging Guides

阅读中文版本

Node.js — ETIMEDOUT or socket hang up on outbound requests

Diagnose ETIMEDOUT by separating network reachability, firewall drops and missing client timeouts.

intermediatedebuggingnodenetworking

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 443

Interpretation

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-xxx

Interpretation

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