How to fix Error: request timeout after 30000ms (HTTP request did not complete) in Node.js
HTTP requests fail when they exceed the configured timeout threshold, typically defaulting to 30 seconds. This occurs when the remote server is slow to respond, network connections are unstable, or response payloads are too large to process within the timeout window.
Quick fix
Fixes ETIMEDOUT
const axios = require('axios');
// Set timeout for specific request
const response = await axios.get('https://api.example.com/data', {
timeout: 60000 // 60 seconds
});
// Or configure globally
const client = axios.create({
timeout: 60000,
baseURL: 'https://api.example.com'
});- Increase timeout for legitimate long-running operations
- Implement retry logic with exponential backoff
- Configure connection pooling and keep-alive settings
- Implement proper timeout error handling
const axios = require('axios');// Set timeout for specific requestconst response = await axios.get('https://api.example.com/data', {timeout: 60000 // 60 seconds});// Or configure globallyconst client = axios.create({timeout: 60000,baseURL: 'https://api.example.com'});Error: request timeout after 30000ms (HTTP request did not complete)
What this error means
This error occurs when an HTTP client request (using axios, fetch, or native http/https modules) exceeds its configured timeout threshold before receiving a complete response from the remote server. The default timeout of 30000ms (30 seconds) is a common configuration across many Node.js HTTP libraries. The timeout mechanism protects your application from hanging indefinitely when remote services are unresponsive. When triggered, it immediately aborts the request and throws this error, allowing your application to handle the failure gracefully rather than waiting forever for a response that may never arrive. This is distinct from connection errors (ECONNREFUSED) or network errors (ECONNRESET) - the connection was established successfully, but the server failed to send a complete response within the allowed time.
Typical symptoms
- HTTP requests consistently fail after exactly 30 seconds
- Error occurs when calling external APIs or microservices
- Requests succeed locally but timeout in production environments
- Large file downloads or uploads fail with timeout errors
- API calls work intermittently, timing out during high load periods
- Error messages include "request timeout", "ETIMEDOUT", or specific millisecond values
Common causes
- Remote server is slow to respond or experiencing high load
- Network latency between client and server is excessive
- Response payload is too large to transfer within the timeout window
- Server is processing long-running operations without streaming responses
- Default timeout value (30000ms) is too aggressive for the operation
- Firewall or proxy is silently dropping packets without closing the connection
- DNS resolution delays consume part of the timeout budget
- Connection pooling issues cause requests to queue longer than expected
How to fix "Error: request timeout after 30000ms (HTTP request did not complete)"
If the operation genuinely requires more time, configure a higher timeout value. For axios:
const axios = require('axios');
// Set timeout for specific request
const response = await axios.get('https://api.example.com/data', {
timeout: 60000 // 60 seconds
});
// Or configure globally
const client = axios.create({
timeout: 60000,
baseURL: 'https://api.example.com'
});For native fetch API (Node.js 18+):
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 60000);
try {
const response = await fetch('https://api.example.com/data', {
signal: controller.signal
});
clearTimeout(timeoutId);
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
}
}For native http/https modules:
const https = require('https');
const options = {
hostname: 'api.example.com',
path: '/data',
timeout: 60000
};
const req = https.get(options, (res) => {
// Handle response
});
req.on('timeout', () => {
req.destroy();
console.error('Request timed out');
});For transient timeout issues, add automatic retry mechanisms:
const axios = require('axios');
async function fetchWithRetry(url, maxRetries = 3, baseDelay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await axios.get(url, { timeout: 30000 });
return response.data;
} catch (error) {
if (error.code === 'ECONNABORTED' && i < maxRetries - 1) {
const delay = baseDelay * Math.pow(2, i);
console.log(`Request timeout, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
// Usage
try {
const data = await fetchWithRetry('https://api.example.com/data');
console.log(data);
} catch (error) {
console.error('Request failed after retries:', error.message);
}Optimize connection management to reduce overhead:
const axios = require('axios');
const http = require('http');
const https = require('https');
// Create HTTP agents with connection pooling
const httpAgent = new http.Agent({
keepAlive: true,
keepAliveMsecs: 30000,
maxSockets: 50,
maxFreeSockets: 10,
timeout: 60000
});
const httpsAgent = new https.Agent({
keepAlive: true,
keepAliveMsecs: 30000,
maxSockets: 50,
maxFreeSockets: 10,
timeout: 60000
});
// Use agents with axios
const client = axios.create({
httpAgent,
httpsAgent,
timeout: 30000
});This reduces connection establishment overhead and prevents socket exhaustion.
Distinguish timeout errors from other failures and handle appropriately:
const axios = require('axios');
async function makeRequest(url) {
try {
const response = await axios.get(url, { timeout: 30000 });
return response.data;
} catch (error) {
if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
console.error('Request timeout:', {
url: error.config?.url,
timeout: error.config?.timeout,
duration: Date.now() - error.config?.startTime
});
// Return cached data, default value, or rethrow
throw new Error('Service temporarily unavailable');
}
if (error.response) {
// Server responded with error status
console.error('Server error:', error.response.status);
} else if (error.request) {
// Request made but no response received
console.error('No response received');
}
throw error;
}
}
// Add request timing for debugging
axios.interceptors.request.use(config => {
config.startTime = Date.now();
return config;
});
axios.interceptors.response.use(
response => {
const duration = Date.now() - response.config.startTime;
console.log(`Request completed in ${duration}ms`);
return response;
},
error => {
if (error.config?.startTime) {
const duration = Date.now() - error.config.startTime;
console.error(`Request failed after ${duration}ms`);
}
return Promise.reject(error);
}
);Investigate the root cause of timeouts:
const axios = require('axios');
const { performance } = require('perf_hooks');
// Create detailed timing logger
function createTimingLogger() {
return {
dnsLookupStart: 0,
tcpConnectionStart: 0,
tlsHandshakeStart: 0,
requestStart: 0,
responseStart: 0,
responseEnd: 0
};
}
// Log request with detailed timing
async function debugRequest(url) {
const timing = createTimingLogger();
const startTime = performance.now();
try {
const response = await axios.get(url, {
timeout: 30000,
onDownloadProgress: (progressEvent) => {
if (!timing.responseStart) {
timing.responseStart = performance.now() - startTime;
}
}
});
timing.responseEnd = performance.now() - startTime;
console.log('Request timing breakdown:', {
total: `${timing.responseEnd.toFixed(2)}ms`,
url,
size: response.headers['content-length'],
status: response.status
});
return response;
} catch (error) {
const failTime = performance.now() - startTime;
console.error('Request failed:', {
url,
duration: `${failTime.toFixed(2)}ms`,
error: error.code || error.message,
timeout: error.config?.timeout
});
throw error;
}
}
// Usage
debugRequest('https://api.example.com/data');Check network latency:
# Test DNS resolution time
time nslookup api.example.com
# Test connection time
time curl -o /dev/null -s -w "Total time: %{time_total}s\n" https://api.example.com/data
# Trace route to identify network hops
traceroute api.example.comAdvanced notes
Timeout Hierarchy: Different timeout types exist in HTTP requests - DNS timeout, connection timeout, socket timeout, and response timeout. The "request timeout" typically encompasses all phases. Understanding which phase is slow helps target optimizations.
Server-Side Considerations: If you control the server, implement streaming responses for large payloads, optimize database queries, add response compression, and consider pagination for large datasets. Long-running operations should use webhooks or polling patterns rather than synchronous requests.
Environment-Specific Timeouts: Cloud functions (AWS Lambda, Google Cloud Functions) have hard execution limits (typically 30-900 seconds). Set your HTTP timeouts well below these limits to ensure graceful error handling. Container orchestrators like Kubernetes have their own timeout configurations that may override application settings.
Global vs Local Timeouts: Setting timeouts globally affects all requests. For APIs with mixed operation durations, configure timeouts per-endpoint:
const fastEndpoint = await axios.get('/quick', { timeout: 5000 });
const slowEndpoint = await axios.get('/report', { timeout: 120000 });Debugging Techniques: Use tools like tcpdump, wireshark, or Node.js built-in diagnostics to capture network traffic. Enable debug logging in HTTP libraries (axios has axios.defaults.debug = true in some configurations).
Related Error Codes: ECONNABORTED (connection aborted), ESOCKETTIMEDOUT (socket-level timeout), and ETIMEDOUT are often used interchangeably depending on the HTTP library. Always check both error.code and error.message for robust error handling.
Frequently asked questions
- What does "ETIMEDOUT" mean?
- This error occurs when an HTTP client request (using axios, fetch, or native http/https modules) exceeds its configured timeout threshold before receiving a complete response from the remote server. js HTTP libraries. The timeout mechanism protects your application from hanging indefinitely when remote services are unresponsive.
- How do I fix "ETIMEDOUT"?
- HTTP requests fail when they exceed the configured timeout threshold, typically defaulting to 30 seconds. This occurs when the remote server is slow to respond, network connections are unstable, or response payloads are too large to process within the timeout window.
- What causes "ETIMEDOUT"?
- Remote server is slow to respond or experiencing high load Network latency between client and server is excessive Response payload is too large to transfer within the timeout window
- Is the "ETIMEDOUT" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐Node.js Official Documentation
- ๐
- ๐Node.js Documentation - HTTP Module(Official Docs)
- ๐
- ๐