Logo
Skip to main content
Development
8 min read

NodeJS Error: ETIMEDOUT Connection timed out

D

Divya Mahi

January 6, 2024 · Updated January 6, 2024

NodeJS Error_ ETIMEDOUT, Connection timed out

Resolving "NodeJS Error: ETIMEDOUT, Connection Timed Out": A Complete Guide

Introduction

In the world of Node.js development, network communication is key. However, a common hurdle faced by developers is the "NodeJS Error: ETIMEDOUT, Connection timed out." This error surfaces when a network request or connection takes too long to respond, often leading to a failure in the communication process. Understanding and effectively handling this error is crucial for developers dealing with external API calls, database connections, or any form of network communication. This blog post aims to demystify this error, exploring its causes, implications, and solutions.

// ✅ Set connection and response timeouts
const http = require('http');

const options = {
  hostname: 'api.example.com',
  port: 80,
  path: '/data',
  timeout: 5000 // 5 second timeout
};

const req = http.get(options, (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => console.log(JSON.parse(data)));
});

req.on('timeout', () => {
  console.error('Connection timed out');
  req.destroy(); // Clean up
});

req.on('error', (err) => {
  console.error('Request failed:', err.message);
});

// ✅ Using fetch with timeout (Node 18+)
async function fetchWithTimeout(url, ms = 5000) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), ms);
  try {
    const res = await fetch(url, { signal: controller.signal });
    return await res.json();
  } finally {
    clearTimeout(timer);
  }
}

Understanding the Error

"ETIMEDOUT" is an error code in Node.js that stands for "Connection Timed Out." It occurs when a network request does not complete within the specified or default time limit. This could be due to server overload, network issues, or an unresponsive external service. This error is most commonly seen in HTTP requests, database connections, or socket programming.

const http = require('http');

// Connection times out when server is unresponsive
const req = http.get('http://unresponsive-server.com/api');
// Error: ETIMEDOUT - Connection timed out

Diving Deeper

Timeouts are important for preventing a program from waiting indefinitely for a response. However, they also need to be handled correctly to ensure robust and responsive applications. Let’s explore common scenarios where this error can occur and how to address them effectively.

Common Scenarios and Fixes with Example Code Snippets

Scenario 1: HTTP Request Timeout

Problematic Code:

const http = require('http');

// No timeout set — hangs indefinitely if server doesn't respond
http.get('http://slow-server.com/api', (res) => {
  console.log(res.statusCode);
});

Explanation: The request might time out if the server is slow or unresponsive.

Solution:

const http = require('http');

const req = http.get('http://slow-server.com/api', {
  timeout: 5000 // 5 second timeout
}, (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => console.log(data));
});

req.on('timeout', () => {
  req.destroy();
  console.error('Request timed out after 5 seconds');
});

req.on('error', (err) => {
  if (err.code === 'ETIMEDOUT') {
    console.error('Connection timed out. Check server availability.');
  }
});

Explanation: Setting a longer timeout and handling the 'timeout' event can mitigate this error.

Scenario 2: Database Connection Timeout

Problematic Code:

const mongoose = require('mongoose');

// No timeout configuration
mongoose.connect('mongodb://remote-db:27017/app');

Explanation: The database connection may time out if the server is not available or slow.

Solution:

const mongoose = require('mongoose');

mongoose.connect('mongodb://remote-db:27017/app', {
  connectTimeoutMS: 10000,
  socketTimeoutMS: 45000,
  serverSelectionTimeoutMS: 5000,
}).then(() => {
  console.log('Database connected');
}).catch((err) => {
  if (err.message.includes('ETIMEDOUT')) {
    console.error('Database connection timed out. Check network/host.');
  }
});

Explanation: Increasing the connection timeout for the database helps handle slow connections better.

Scenario 3: Socket Connection Timeout

Problematic Code:

const net = require('net');

const socket = net.connect(8080, 'remote-host.com');
socket.on('data', (data) => console.log(data.toString()));

Explanation: A socket connection may fail to establish within the default timeout period.

Solution:

const net = require('net');

const socket = net.connect(8080, 'remote-host.com');
socket.setTimeout(5000);

socket.on('timeout', () => {
  console.error('Socket connection timed out');
  socket.destroy();
});

socket.on('data', (data) => console.log(data.toString()));
socket.on('error', (err) => console.error('Socket error:', err.message));

Explanation: Adjusting the socket timeout and handling the 'timeout' event can prevent the error.

Scenario 4: External API Request Timeout

Problematic Code:

const https = require('https');

// Calling an external API without timeout
https.get('https://api.third-party.com/data', (res) => {
  let body = '';
  res.on('data', chunk => body += chunk);
  res.on('end', () => console.log(body));
});

Explanation: The request to an external API might time out due to various reasons, such as server overload.

Solution:

const https = require('https');

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

const req = https.get('https://api.third-party.com/data', {
  signal: controller.signal
}, (res) => {
  let body = '';
  res.on('data', chunk => body += chunk);
  res.on('end', () => {
    clearTimeout(timeout);
    console.log(body);
  });
});

req.on('error', (err) => {
  clearTimeout(timeout);
  if (err.code === 'ABORT_ERR') {
    console.error('Request aborted due to timeout');
  }
});

Explanation: Setting a custom timeout for external API requests can help handle slower responses.

Scenario 5: Long-Running HTTP POST Request

Problematic Code:

const http = require('http');

const data = JSON.stringify({ largeData: '...' });
const req = http.request({
  hostname: 'api.example.com',
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}, (res) => {
  console.log(res.statusCode);
});

req.write(data);
req.end();

Explanation: A large payload might take longer to send, leading to a timeout error.

Solution:

const http = require('http');

const data = JSON.stringify({ largeData: '...' });
const req = http.request({
  hostname: 'api.example.com',
  method: 'POST',
  timeout: 30000, // 30 second timeout for large uploads
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(data)
  }
}, (res) => {
  console.log('Status:', res.statusCode);
});

req.on('timeout', () => {
  req.destroy(new Error('Upload timed out'));
});

req.on('error', (err) => {
  console.error('Request error:', err.message);
});

req.write(data);
req.end();

Explanation: Increasing the timeout value gives the request more time to complete, preventing premature timeouts.

Scenario 6: Streaming Data to a Slow Server

Problematic Code:

const http = require('http');
const fs = require('fs');

const req = http.request({ hostname: 'upload.example.com', method: 'PUT' });
fs.createReadStream('large-file.zip').pipe(req);

Explanation: Streaming a large file to a server might take longer than the server's default timeout.

Solution:

const http = require('http');
const fs = require('fs');

const req = http.request({
  hostname: 'upload.example.com',
  method: 'PUT',
  timeout: 60000
}, (res) => {
  console.log('Upload status:', res.statusCode);
});

req.on('timeout', () => {
  req.destroy(new Error('Upload stream timed out'));
});

req.on('error', (err) => {
  console.error('Upload error:', err.message);
});

const stream = fs.createReadStream('large-file.zip');
stream.on('error', (err) => {
  req.destroy(err);
});
stream.pipe(req);

Explanation: Setting a higher timeout on the request allows enough time for the entire stream to be sent.

Scenario 7: Cloud Service API Request Timeout

Problematic Code:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

// No timeout for cloud service
s3.getObject({ Bucket: 'my-bucket', Key: 'large-file' }).promise()
  .then(data => console.log(data));

Explanation: Queries to large datasets in cloud services might exceed the default request timeout.

Solution:

const AWS = require('aws-sdk');

const s3 = new AWS.S3({
  httpOptions: {
    timeout: 30000, // 30 second timeout
    connectTimeout: 5000 // 5 second connect timeout
  },
  maxRetries: 3,
});

s3.getObject({ Bucket: 'my-bucket', Key: 'large-file' }).promise()
  .then(data => console.log('Retrieved', data.ContentLength, 'bytes'))
  .catch(err => {
    if (err.code === 'TimeoutError') {
      console.error('S3 request timed out. Check network or file size.');
    }
  });

Explanation: Adjusting the client's timeout setting can prevent timeouts with large queries.

Scenario 8: WebSocket Connection Timeout

Problematic Code:

const WebSocket = require('ws');

// No connection timeout
const ws = new WebSocket('ws://remote-server:8080');
ws.on('open', () => console.log('Connected'));

Explanation: The WebSocket might timeout during connection setup, especially if the server is slow or busy.

Solution:

const WebSocket = require('ws');

const ws = new WebSocket('ws://remote-server:8080', {
  handshakeTimeout: 5000 // 5 second handshake timeout
});

const connectTimeout = setTimeout(() => {
  if (ws.readyState !== WebSocket.OPEN) {
    ws.terminate();
    console.error('WebSocket connection timed out');
  }
}, 10000);

ws.on('open', () => {
  clearTimeout(connectTimeout);
  console.log('Connected');
});

ws.on('error', (err) => {
  clearTimeout(connectTimeout);
  console.error('WebSocket error:', err.message);
});

Explanation: Increasing the WebSocket handshake timeout allows more time for the connection to be established.

Strategies to Prevent Errors

Proper Timeout Settings: Adjust timeout settings based on the expected response time of the server or service.

Robust Error Handling: Implement comprehensive error handling for all network requests to handle timeouts gracefully.

Retry Mechanisms: Implement retry logic for failed requests due to timeouts.

Monitoring and Logging: Use monitoring tools to identify and log timeout issues for further analysis.

Best Practices

Assess Network Requirements: Understand the network conditions and server response times to set appropriate timeouts.

Keep Dependencies Updated: Ensure all networking libraries and dependencies are up to date.

Test under Different Conditions: Test your application under various network scenarios to understand its behavior during timeouts.

User Feedback: Provide immediate feedback to users in case of a timeout, especially in UI-driven applications.

Conclusion

"NodeJS Error: ETIMEDOUT, Connection timed out" is a common error that can be effectively managed with proper timeout handling, error catching, and network strategy. By employing the recommended practices and understanding the nuances of network communication in Node.js, developers can create more resilient and user-friendly applications. Remember, handling network timeouts is not just about avoiding errors, but also about enhancing the overall user experience.

Development
D

Written by

Divya Mahi

Building innovative digital solutions at Poulima InfoTech. We specialize in web & mobile app development using React, Next.js, Flutter, and AI technologies.

Ready to Build Your Next Project?

Transform your ideas into reality with our expert development team. Let's discuss your vision.

Continue Reading

Related Articles