How to fix TimeoutError: Operation timed out after 5000ms in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025· 291 views

This error occurs when an asynchronous operation exceeds its configured time limit without completing. Common in network requests, database queries, and long-running async operations.

Quick fix

Fixes TIMEOUT

// HTTP client timeout
const response = await fetch('https://api.example.com', {
  signal: AbortSignal.timeout(5000) // 5 second timeout
});

// Promise timeout with Promise.race()
const timeout = new Promise((_, reject) =>
  setTimeout(() => reject(new Error('TimeoutError: Operation timed out')), 5000)
);
const result = await Promise.race([operation(), timeout]);

// Database client timeout
const result = await db.query('SELECT * FROM users', {
  timeout: 5000
});
  1. Identify where the timeout is configured
  2. Verify the operation actually takes too long
  3. Increase timeout for legitimate long-running operations
  4. Optimize slow operations
node.js — error
// HTTP client timeout
const response = await fetch('https://api.example.com', {
signal: AbortSignal.timeout(5000) // 5 second timeout
});
// Promise timeout with Promise.race()
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('TimeoutError: Operation timed out')), 5000)
);
const result = await Promise.race([operation(), timeout]);
// Database client timeout
const result = await db.query('SELECT * FROM users', {
timeout: 5000
});
TimeoutError: Operation timed out after 5000ms

What this error means

A TimeoutError is thrown when an async operation takes longer than the specified timeout duration. This is typically a deliberate safeguard to prevent operations from hanging indefinitely and consuming resources. In Node.js, timeouts can be implemented using Promise.race(), AbortController with AbortSignal.timeout(), or third-party libraries like Bluebird. The error indicates that while the operation may still be running, the caller has decided to stop waiting for it. Unlike connection errors or permission issues, a timeout doesn't necessarily mean the operation failed—it means it didn't complete within the expected timeframe. The underlying operation may still succeed later, but the result will be discarded.

Typical symptoms

  • Error message includes "TimeoutError" or "Operation timed out"
  • Async operations hang before eventually failing
  • API requests or database queries fail after a specific duration
  • Promise.race() rejects with timeout error before operation completes
  • Network requests fail with timeout status in logs
  • Application shows delays before throwing timeout errors

Common causes

  1. Network latency or slow external API responses exceeding timeout threshold
  2. Database queries taking longer than configured timeout (complex joins, missing indexes)
  3. Timeout value set too low for the operation's actual requirements
  4. Resource contention causing operations to queue and delay
  5. Connection pool exhaustion forcing new operations to wait
  6. Blocking operations in event loop preventing async callbacks from executing
  7. DNS resolution delays when connecting to external services
  8. Server overload causing request processing delays

How to fix "TimeoutError: Operation timed out after 5000ms"

1Identify where the timeout is configured

Review your code to find where the timeout is set. Common locations include:

javascript
// HTTP client timeout
const response = await fetch('https://api.example.com', {
  signal: AbortSignal.timeout(5000) // 5 second timeout
});

// Promise timeout with Promise.race()
const timeout = new Promise((_, reject) =>
  setTimeout(() => reject(new Error('TimeoutError: Operation timed out')), 5000)
);
const result = await Promise.race([operation(), timeout]);

// Database client timeout
const result = await db.query('SELECT * FROM users', {
  timeout: 5000
});

Check configuration files, HTTP client settings, and database connection options.

2Verify the operation actually takes too long

Add logging to measure actual operation duration:

javascript
const startTime = Date.now();
try {
  const result = await someAsyncOperation();
  console.log(`Operation completed in ${Date.now() - startTime}ms`);
} catch (error) {
  console.log(`Operation failed after ${Date.now() - startTime}ms`);
  console.error(error);
}

This helps determine if the timeout is too aggressive or if the operation genuinely needs optimization.

3Increase timeout for legitimate long-running operations

If operations legitimately require more time, increase the timeout:

javascript
// Using AbortSignal.timeout() (Node.js 16+)
const response = await fetch('https://slow-api.example.com', {
  signal: AbortSignal.timeout(30000) // Increase to 30 seconds
});

// Using Promise.race()
const timeout = (ms) => new Promise((_, reject) =>
  setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms)
);

const result = await Promise.race([
  longRunningOperation(),
  timeout(30000) // 30 second timeout
]);

Balance between allowing sufficient time and preventing indefinite hangs.

4Optimize slow operations

For operations that consistently timeout, investigate performance:

Database queries:

javascript
// Add indexes for frequently queried fields
// Before: slow full table scan
const users = await db.users.findMany({
  where: { email: 'user@example.com' }
});

// After: create index on email column
// CREATE INDEX idx_users_email ON users(email);

Network requests:

javascript
// Use connection pooling
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50
});

// Cache frequently accessed data
const cachedData = cache.get(key);
if (cachedData) return cachedData;

const freshData = await fetchFromAPI();
cache.set(key, freshData, 300); // 5 min TTL

Parallelize independent operations:

javascript
// Serial (slow)
const user = await fetchUser(id);
const posts = await fetchPosts(id);
const comments = await fetchComments(id);

// Parallel (fast)
const [user, posts, comments] = await Promise.all([
  fetchUser(id),
  fetchPosts(id),
  fetchComments(id)
]);
5Implement proper timeout error handling

Handle timeout errors gracefully with retry logic and user feedback:

javascript
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, {
        ...options,
        signal: AbortSignal.timeout(5000)
      });
      return response;
    } catch (error) {
      if (error.name === 'TimeoutError' && attempt < maxRetries) {
        console.log(`Attempt ${attempt} timed out, retrying...`);
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); // Exponential backoff
        continue;
      }
      throw error;
    }
  }
}

// Usage
try {
  const data = await fetchWithRetry('https://api.example.com/data');
} catch (error) {
  if (error.name === 'TimeoutError') {
    console.error('Operation timed out after multiple retries');
    // Show user-friendly message
  }
}
6Use AbortController for cancelable operations

Modern Node.js (16+) supports AbortController for proper cancellation:

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

try {
  const response = await fetch('https://api.example.com', {
    signal: controller.signal
  });
  clearTimeout(timeoutId); // Clear if successful
  return await response.json();
} catch (error) {
  if (error.name === 'AbortError') {
    throw new Error('TimeoutError: Operation timed out after 5000ms');
  }
  throw error;
}

This approach properly cancels the underlying operation instead of just discarding the result.

Advanced notes

Promise Continuation After Timeout:
When a timeout occurs using Promise.race(), the original promise continues executing in the background. This can lead to unexpected side effects or resource leaks. Use AbortController to truly cancel operations when timeouts occur.

Event Loop Blocking:
Timeouts rely on the event loop being free to execute callbacks. If synchronous operations block the event loop, timeout handlers may not fire on time. Use --trace-warnings to detect blocking operations.

Distributed Systems Considerations:
In microservices, set timeouts at multiple levels: client timeout < service timeout < load balancer timeout. This ensures proper error propagation without cascading failures.

Timeout Granularity:
Node.js timers have minimum granularity dependent on the system (typically 1-15ms). Very short timeouts may not fire precisely when expected. Use process.hrtime() or performance.now() for high-precision timing measurements.

Memory Leaks:
Always clear timeout handles when operations complete successfully to prevent memory leaks:

javascript
const timeoutId = setTimeout(...);
try {
  await operation();
} finally {
  clearTimeout(timeoutId); // Essential cleanup
}

Frequently asked questions

What does "TIMEOUT" mean?
A TimeoutError is thrown when an async operation takes longer than the specified timeout duration. This is typically a deliberate safeguard to prevent operations from hanging indefinitely and consuming resources. timeout(), or third-party libraries like Bluebird.
How do I fix "TIMEOUT"?
This error occurs when an asynchronous operation exceeds its configured time limit without completing. Common in network requests, database queries, and long-running async operations.
What causes "TIMEOUT"?
Network latency or slow external API responses exceeding timeout threshold Database queries taking longer than configured timeout (complex joins, missing indexes) Timeout value set too low for the operation's actual requirements
Is the "TIMEOUT" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading