Axios Network Error: Every Cause and How to Fix It
Quick answer
💡Axios throws a Network Error when the request cannot complete at the transport layer — meaning no HTTP response is received at all. This is distinct from a 4xx or 5xx error where a response exists. Common causes are ECONNREFUSED (server not listening on the port), CORS blocking the response in the browser, a certificate error in Node.js, or a connection timeout. Inspect error.code on the caught AxiosError to narrow down which failure occurred, then address that specific layer.
Error symptoms
- ✕
AxiosError: Network Error with no HTTP status code on error.response - ✕
error.code is ECONNREFUSED when the target port is not listening - ✕
error.code is ETIMEDOUT when the request exceeded the configured timeout - ✕
error.code is ECONNABORTED when Axios itself cancelled the request due to timeout - ✕
In the browser, DevTools Console shows net::ERR_FAILED or a CORS policy error alongside the Axios error - ✕
error.request exists but error.response is undefined, meaning the request was sent but no response arrived
Common causes
- •The target server is not running on the expected host and port — ECONNREFUSED is the TCP-level signal
- •baseURL has a trailing slash and the request URL has a leading slash, producing a malformed double-slash URL
- •Browser CORS policy blocks the response — Axios wraps all CORS failures as Network Error with no status code
- •Node.js HTTPS certificate validation fails because the server uses a self-signed or expired certificate
- •The configured timeout in milliseconds is too short for the server's actual response time
- •An HTTP proxy intercepting the request is not reachable or returns a connection reset
When it happens
- •Connecting to a local development server that is not yet started or crashed
- •Making API calls from a browser to a backend on a different origin without CORS headers configured
- •Running Node.js scripts that call APIs protected by corporate proxies or VPNs
- •Deploying to a new environment where environment variables for base URLs point to the wrong host
- •Using Axios in React Native where network permissions or proxy settings differ from a browser
Examples and fixes
Axios throws Network Error when the TCP connection is refused, wrapping ECONNREFUSED without exposing the status code.
ECONNREFUSED: wrong port or server not running
❌ Wrong
const axios = require('axios');
// Server is running on port 3001 but we call 3000
axios.get('http://localhost:3000/api/users')
.then(res => console.log(res.data))
.catch(err => {
// This only shows 'Network Error' — not the real reason
console.error(err.message);
});✅ Fixed
const axios = require('axios');
axios.get('http://localhost:3001/api/users')
.then(res => console.log(res.data))
.catch(err => {
if (err.code === 'ECONNREFUSED') {
console.error(`Server not reachable at ${err.config.url}`);
console.error('Check that the server is running on the correct port');
} else if (err.response) {
// Got a response with error status
console.error(`HTTP ${err.response.status}:`, err.response.data);
} else {
console.error('Network error:', err.code, err.message);
}
});Axios wraps all transport-level failures under the string 'Network Error' in error.message, which hides the real cause. The error.code property contains the Node.js system error code, which is far more diagnostic. ECONNREFUSED means the operating system tried to open a TCP connection and the target port actively rejected it — the server is either not running or not listening on that port. The fix corrects the port and adds structured error handling that distinguishes between transport failures (no error.response), HTTP error responses (error.response exists), and request-level failures (error.request but no error.response). This three-way check is the standard Axios error handling pattern described in the official Axios documentation.
In the browser, Axios reports Network Error for CORS failures because the browser hides the actual response from JavaScript when CORS headers are missing.
Browser CORS masking as Network Error
❌ Wrong
// React component — server has no CORS headers
import axios from 'axios';
async function loadUserProfile(userId) {
// This call goes to a different origin with no CORS headers
const res = await axios.get(
`https://api.internal.company.com/users/${userId}`
);
return res.data;
}
// Catches 'Network Error' with no further info
loadUserProfile('abc123').catch(console.error);✅ Fixed
import axios from 'axios';
// Option 1: proxy through same origin (Next.js API route or Express)
async function loadUserProfile(userId) {
const res = await axios.get(`/api/proxy/users/${userId}`);
return res.data;
}
// Option 2: configure CORS on the backend
// Backend (Express):
// const cors = require('cors');
// app.use(cors({ origin: 'https://app.company.com', credentials: true }));
// Option 3: detect CORS failures with interceptors
axios.interceptors.response.use(null, (error) => {
if (!error.response && error.message === 'Network Error') {
console.warn('Possible CORS failure — check Network tab for OPTIONS request');
}
return Promise.reject(error);
});The browser's security model prevents JavaScript from reading the response body or status code when a CORS check fails. Axios receives a network-level abort from the browser and has no information about whether the server responded with 200, 403, or 500. The only signal is that error.response is undefined. This makes CORS failures indistinguishable from genuine network outages at the Axios layer. The fix shows three approaches: proxying through the same origin avoids the CORS issue entirely; configuring CORS on the backend is the direct solution; and adding a response interceptor at least provides a useful console warning that points developers toward the Network tab where the real CORS error appears.
Adding automatic retry for network errors and 5xx responses using the axios-retry package.
Retry logic with axios-retry for transient failures
❌ Wrong
const axios = require('axios');
// No retry — one failure drops the request
async function fetchOrderStatus(orderId) {
const res = await axios.get(
`https://api.example.com/orders/${orderId}`,
{ timeout: 5000 }
);
return res.data;
}✅ Fixed
const axios = require('axios');
const axiosRetry = require('axios-retry').default;
const client = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` }
});
axiosRetry(client, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) =>
axiosRetry.isNetworkError(error) ||
axiosRetry.isRetryableError(error)
});
async function fetchOrderStatus(orderId) {
const res = await client.get(`/orders/${orderId}`);
return res.data;
}Network errors from Axios are often transient — a momentary DNS hiccup, a pod restart in Kubernetes, or a brief connection pool exhaustion on the server side. A single failure without retry causes cascading user-visible errors that a simple retry would have recovered from. The axios-retry package attaches to an Axios instance and automatically retries on network errors and server errors that indicate retryability. Using exponentialDelay adds increasing wait times between retries to avoid overwhelming a struggling server. The retryCondition function controls which errors are retried: isNetworkError covers ECONNREFUSED, ETIMEDOUT, and ECONNABORTED, while isRetryableError adds 429 and 5xx responses. Idempotent requests like GET and HEAD are safe to retry unconditionally; be more careful retrying POST requests.
What Axios Network Error actually means
Axios uses the string 'Network Error' for any failure that prevents receiving an HTTP response. This single error message covers a wide range of underlying causes, which is why it frustrates developers so much. When you log error.message and see 'Network Error', you need to look at three other properties to understand what actually happened: error.code contains the system-level error code such as ECONNREFUSED, ETIMEDOUT, or ECONNABORTED. The error.request property contains the underlying XMLHttpRequest or http.ClientRequest object, confirming the request was dispatched. The error.response property being undefined confirms no HTTP response was received.
In Node.js environments, the most frequent cause is ECONNREFUSED, which means the operating system's TCP stack tried to open a connection and the target host actively sent a RST packet back — meaning nothing is listening on that port. This happens when the target server is not running, when you have the wrong port in your base URL, or when a firewall is blocking the connection. ETIMEDOUT means the connection attempt timed out waiting for the TCP handshake to complete, which usually points to a firewall silently dropping packets rather than rejecting them. ECONNABORTED is Axios-specific: it means Axios itself cancelled the request because the configured timeout in milliseconds was exceeded after the connection was established.
In browser environments, the same 'Network Error' string appears for an entirely different reason: CORS violations. When the browser's CORS enforcement blocks a response, it does not expose the response to JavaScript at all. Axios sees a network abort from the browser and produces a Network Error with no status code. A failed CORS preflight and a genuine server outage look identical to Axios running in the browser. The only way to distinguish them is to open the browser's DevTools Network tab and look for the actual HTTP status code on the request — the browser can show it even though JavaScript cannot read it.
BaseURL configuration errors are another common source of Network Error that has nothing to do with the network itself. When baseURL ends with a trailing slash and the path passed to axios.get() begins with a leading slash, the resulting URL contains a double slash. Some servers treat double-slash URLs as 404, others as 400, and some redirect — but if the URL becomes malformed enough to be syntactically invalid, Axios may fail before even sending the request.
Narrowing down the real failure layer
Start by logging the full error object structure rather than just error.message. In a catch block, print error.code, Boolean(error.response), Boolean(error.request), and error.config.url. These four values tell you which of the three Axios failure categories you are in: transport failure with no response, request sent but no response received, or a response received but with an error status.
In the browser, open DevTools before triggering the request. Go to the Network tab and find the failing request. Click on it and check the Status column — the browser can display the HTTP status even when JavaScript cannot access the response due to CORS. If the status shows 200 but Axios still throws Network Error, this is almost certainly a CORS issue where Access-Control-Allow-Origin is missing on the response. If the Network tab shows the request as cancelled or stuck with a timing bar that never completes, the server connection is failing at the TCP level.
To confirm CORS is the issue in a browser environment, open the Console tab immediately after the Network Error appears. Chrome displays an explicit message like 'has been blocked by CORS policy: No Access-Control-Allow-Origin header is present'. This message appears even though Axios only exposes the generic Network Error. The /tools/cors-tester on ToolDock lets you send a real request from a different origin and inspect the response headers directly.
For Node.js, reproduce the request using the built-in http module or with curl to eliminate Axios-specific configuration as a variable. If curl succeeds but Axios fails, compare the Axios configuration carefully: check baseURL for trailing slashes, verify the timeout is long enough, and check whether you have set rejectUnauthorized: false for HTTPS requests to servers with self-signed certificates. If both curl and Axios fail, the problem is at the network or server layer and Axios configuration is not to blame.
For debugging through an HTTP proxy like Charles or Fiddler, set the proxy in the Axios config: pass a proxy object with host and port to any Axios call. This lets you inspect the raw request and response bytes, which reveals encoding issues, header stripping, and body serialization problems that are invisible at the Axios API level. Use /tools/http-request-builder to construct and send the same request outside your application code to confirm the API itself responds correctly.
Fixing each type of Axios Network Error
For ECONNREFUSED errors, the fix is straightforward: verify the target host and port are correct and that the service is running. In local development, confirm the backend server started successfully and check which port it is listening on. In production, verify DNS resolution is correct and that any firewall or security group rules allow connections from the client's IP. Use a simple TCP connectivity test before deploying: in Node.js, net.createConnection({ host, port }) can confirm connectivity independent of HTTP or Axios.
For CORS-related Network Errors in the browser, the fix must be on the server. Add CORS headers to the response, handle OPTIONS preflight requests, and ensure Access-Control-Allow-Origin reflects the frontend's exact origin. If you cannot modify the server, add a same-origin proxy in your Next.js API routes or Express server that forwards requests to the third-party API. The proxy approach lets the browser call your own domain, which is always same-origin, while your backend makes the actual cross-origin request without browser CORS enforcement.
For ETIMEDOUT and ECONNABORTED errors, evaluate whether the timeout value is appropriate for the operation. A 5000ms timeout is fine for simple reads but inappropriate for uploads or long-running queries. Set different timeout values per request type using the timeout option in individual axios.get() or axios.post() calls. For operations with unpredictable duration, use an AbortController signal instead of a fixed timeout to allow the calling code to cancel based on user actions.
For TLS certificate errors in Node.js (typically seen as UNABLE_TO_VERIFY_LEAF_SIGNATURE or CERT_HAS_EXPIRED), the root cause is that the server's certificate does not pass Node.js's certificate validation. In development, setting httpsAgent: new https.Agent({ rejectUnauthorized: false }) disables validation, but never use this in production. In production, ensure the server has a valid certificate from a trusted CA and that the Node.js process has access to the system's CA bundle. If calling an internal service with a private CA, add the CA certificate to the httpsAgent configuration rather than disabling validation entirely.
Double-slash URL issues from trailing/leading slash combinations are fixed by standardizing the baseURL to end without a slash and all path parameters to begin with a slash. Use URL template literals carefully and add a simple unit test that constructs the final URL and asserts no double slash appears.
Axios 1.x changes that break existing code
Axios version 1.0 introduced changes to the error format that broke code written against 0.x versions. The most significant change is that axios-retry and custom retry logic based on error properties may behave differently because the internal error shape changed. If you upgraded from Axios 0.21 to 1.x and existing retry logic stopped working, audit every place that reads error.config, error.isAxiosError, or error.toJSON().
In Axios 1.x, the CanceledError class replaced CancelError. Code that checked err instanceof axios.Cancel for cancellation detection needs to be updated to check for axios.isCancel(err) or err instanceof axios.CanceledError. This matters when using AbortController signals to cancel requests — the error thrown when a signal is aborted is a CanceledError, not a Network Error, so they should be handled separately.
The behavior of axios.interceptors.response.use(null, handler) changed subtly in 1.x in how it handles responses inside the error handler. In 0.x, returning a resolved value from the error handler would silently swallow the error and treat it as a successful response. This behavior was intentional for retry patterns but confused developers. Verify that any retry logic in interceptors correctly re-throws when it exhausts retries rather than silently returning undefined.
HTTP/2 support in Axios for Node.js is not native — Axios uses the http and https modules which are HTTP/1.1 only. If the target API requires HTTP/2 (which is rare but exists for some gRPC-HTTP bridges), Axios will fail with a protocol negotiation error that appears as a Network Error. In those cases, use undici or node-fetch with an HTTP/2 transport instead.
Axios running in React Native uses a different network adapter from browser Axios. Metro bundler resolves the Axios source differently, and the XMLHttpRequest polyfill in React Native has different timeout and redirect behavior. If Axios Network Errors appear only in React Native and not in the browser, check the React Native network debug tool and verify that the device's proxy or VPN configuration is not intercepting requests.
Common Axios configuration errors to avoid
Setting a global default timeout too short is one of the most common Axios configuration mistakes. When you call axios.defaults.timeout = 3000 at application startup, every request in the app — including slow file uploads, long-running reports, and health check endpoints — shares that 3-second limit. Instead, set a reasonable global default like 10000ms and override it per-request type. Upload endpoints typically need 60000ms or more. Ping endpoints can stay at 2000ms. The timeout option in individual axios calls overrides the global default.
Formatting the baseURL incorrectly leads to request URLs that look valid in code but are malformed when constructed. axios.create({ baseURL: 'https://api.example.com/v1/' }) combined with client.get('/users') produces https://api.example.com/users — the v1 segment is dropped because of how URL joining works. The rule is: baseURL should not end with a slash, and path segments passed to get(), post(), etc. should begin with a slash.
Not using axios.create() and instead using the global axios instance causes shared state problems in Node.js servers. If request interceptors, response interceptors, or default headers are added to the global axios instance in one part of the code, they affect all requests everywhere in the process. Always create isolated Axios instances for different API clients using axios.create() so each client has its own configuration and interceptors.
Ignoring the difference between error.response, error.request, and the error itself is the root cause of most Axios error handling bugs. Logging only error.message gives 'Network Error' or 'Request failed with status code 403' with no further context. Proper error handling reads error.response.data when a response exists, error.config.url to know which URL failed, and error.code for transport-level failures. Building a centralized error handler that captures all three cases produces logs that are actually useful when debugging production issues.
Patterns for production-ready Axios clients
Create one Axios instance per external API your application talks to. Each instance gets its own baseURL, default headers like Authorization, and interceptors appropriate for that API. This isolation prevents configuration bleeding between API clients and makes it easy to mock specific instances in tests. Export the instances as singletons from a dedicated file — for example, a stripeClient.js that holds the Stripe API client with its API key header — so every part of the application uses the same configured instance.
Add a request interceptor that logs outgoing request metadata: method, URL, and a correlation ID that can be traced through server logs. Add a response interceptor that logs the status code and response time. Never log request bodies containing passwords, API keys, or PII — log only headers and status codes unless you are in a development environment with a debug flag set. These logs, forwarded to a tool like Datadog or CloudWatch, cut the time to diagnose production API failures from hours to minutes.
Implement retry logic for idempotent requests using axios-retry with exponential backoff. Configure retries only for network errors and specific status codes like 429 and 503 that indicate the server is temporarily overwhelmed. Do not retry 400, 401, 403, or 422 responses — those are deterministic errors that will not succeed on retry. Set a maximum retry count of 3 and use jitter (random delay variation) in production to prevent all retrying clients from hitting the server at the same moment after a brief outage.
Use the /tools/http-request-builder on ToolDock to validate API endpoints before writing Axios client code. Paste the exact URL, method, and headers you plan to use and confirm the response shape matches your expectations. This prevents writing parsing code against a schema that turns out to be wrong when the real request is made.
For applications that make many simultaneous Axios requests, consider controlling concurrency with a queue like p-queue or bottleneck. When a Node.js application sends hundreds of simultaneous requests, it can exhaust the system's connection pool, leading to ECONNRESET or ETIMEDOUT errors that appear to be server-side issues but are actually client-side connection exhaustion. Limiting concurrency to 10-20 simultaneous requests is a safe ceiling for most APIs.
Quick fix checklist
- ✓Log error.code, Boolean(error.response), Boolean(error.request), and error.config.url in the catch block
- ✓Check error.code: ECONNREFUSED means wrong port, ETIMEDOUT means firewall drop, ECONNABORTED means Axios timeout exceeded
- ✓Open browser DevTools Console — look for an explicit CORS policy error message alongside the Network Error
- ✓In the Network tab, find the failing request and check its actual HTTP status code even if JavaScript cannot read it
- ✓Verify baseURL does not end with a trailing slash if request paths start with a leading slash
- ✓Confirm the server returns Access-Control-Allow-Origin in the response when called from a browser on a different origin
- ✓For Node.js TLS errors, add the server CA certificate to httpsAgent rather than setting rejectUnauthorized: false
- ✓Add axios-retry with exponentialDelay for transient network failures on idempotent requests
Related guides
Frequently asked questions
What is the difference between Axios Network Error and a 5xx error?
A Network Error means no HTTP response was received at all — error.response is undefined. This happens at the transport layer before an HTTP status code exists. A 5xx error means the server responded with a status code in the 500-599 range. Axios throws for both, but error.response exists for 5xx responses and contains the status code and body, while Network Error has only error.code and error.request to explain what happened.
How do I fix Axios Network Error in React when calling my own backend?
If both your React app and backend are on the same domain, check that the backend is running and reachable. If they are on different origins, the browser's CORS policy is the most likely cause. Check the browser Console for a CORS policy message alongside the Network Error. Fix CORS headers on the backend using the cors npm package in Express, or proxy API calls through a Next.js API route to avoid cross-origin requests from the browser.
Why does error.response exist for 404 but not for Network Error?
A 404 response is still a valid HTTP response — the server received the request, understood it, and returned a 404 status. Axios resolves these differently from network-level failures. Network Error occurs when no HTTP response arrives, which happens when the TCP connection fails, the server drops the connection, or CORS causes the browser to abort the request before the response is readable by JavaScript.
Can I make Axios not throw on 4xx and 5xx responses?
Yes. Pass a validateStatus function to Axios that returns true for any status you want treated as success. For example, validateStatus: () => true accepts all status codes without throwing, and you can then check res.status yourself. This is useful when an API intentionally returns 404 for missing resources and you want to handle that case without a try-catch block.
How do I set a timeout in Axios and handle the timeout error?
Set timeout in milliseconds in the Axios config: axios.get(url, { timeout: 5000 }). When the timeout is exceeded after the connection is established, Axios throws with error.code === 'ECONNABORTED'. If the connection itself times out before establishing, error.code is 'ETIMEDOUT'. Check error.code in your catch block to distinguish between these two timeout types and display appropriate messages to users.
Is it safe to use rejectUnauthorized: false in Node.js Axios?
Only in local development against servers with self-signed certificates. Never in production. Setting rejectUnauthorized: false disables all TLS certificate validation, meaning the connection could be intercepted by any man-in-the-middle attacker without detection. In production, add the server's CA certificate to the Axios httpsAgent configuration rather than disabling validation. This allows validation while trusting your specific CA.
How do I debug Axios Network Error in a React Native app?
React Native's XMLHttpRequest polyfill behaves differently from a browser. Enable the Flipper network inspector or use the Reactotron plugin to see raw HTTP traffic. Check that the device's network allows connections to the target host — simulators sometimes have different proxy settings than the development machine. Confirm the API endpoint is reachable from the device by testing with a simple fetch call before blaming Axios configuration.
What does baseURL trailing slash do to Axios request URLs?
URL joining in Axios follows standard URL resolution rules. If baseURL is https://api.example.com/v1/ and the request path is /users, the result is https://api.example.com/users — the /v1/ segment is dropped because the leading slash on /users signals an absolute path from the domain root. To avoid this, keep baseURL without a trailing slash: https://api.example.com/v1, and write all request paths starting with /users, /orders, etc.
All tools run in your browser. Your data never leaves your device. Last updated: 2026-05-06.