Axios Handling of HTTP 304 Not Modified
When the Axios HTTP client receives an HTTP 304 Not Modified response, its behavior depends on default status validation rules and the runtime environment (browser vs. Node.js). By default, Axios treats a 304 status as an error and rejects the request promise because it only considers 2xx status codes successful. This article details why this rejection occurs, how the execution environment impacts the response, and how to properly configure Axios to handle 304 statuses.
Default Status Validation in Axios
Axios determines whether a promise should resolve or reject using the
validateStatus configuration option. By default,
validateStatus is defined as:
validateStatus: function (status) {
return status >= 200 && status < 300;
}Because an HTTP 304 code falls outside the 200–299 range, Axios
creates an AxiosError and rejects the promise. If an
application does not intercept or catch this error, the request fails,
even though HTTP 304 is a standard response indicating that a cached
version of the resource is still valid.
Environment Differences: Browser vs. Node.js
The runtime environment plays a significant role in how a 304 response is surfaced to your code:
- In the Browser: The browser's native networking
layer (
XMLHttpRequestor Fetch API) handles caching automatically. When conditional headers likeIf-None-Match(ETag) orIf-Modified-Sinceare sent, the browser intercepts the server's 304 response, retrieves the content from its local cache, and passes a200 OKstatus with the cached body to Axios. Consequently, developers rarely encounter an unhandled 304 in browser environments unless native caching is manually disabled. - In Node.js: Node.js lacks a built-in HTTP cache.
When Axios makes a request that returns a 304 status, the Node.js HTTP
adapter receives the raw 304 response directly from the server. Because
there is no native cache to resolve the payload, Axios immediately
rejects the promise based on the default
validateStatuscheck.
How to Handle HTTP 304 in Axios
To prevent Axios from throwing an error upon encountering a 304
status, you can customize the validateStatus function in
your request configuration or global Axios instance:
const axios = require('axios');
axios.get('https://api.example.com/data', {
headers: {
'If-None-Match': '"etag-value-12345"'
},
validateStatus: function (status) {
return (status >= 200 && status < 300) || status === 304;
}
})
.then(response => {
if (response.status === 304) {
// Resource has not changed; use application-level cached data
console.log('Resource not modified. Using cached data.');
} else {
// Fresh data received
console.log('Received fresh data:', response.data);
}
})
.catch(error => {
console.error('Request failed:', error);
});Managing Cached Payloads
Accepting an HTTP 304 status via validateStatus does not
automatically populate response.data. A 304 response
typically contains empty response headers and no body. When working in
server-side environments like Node.js, your application architecture
must maintain its own local cache layer (such as Redis, an in-memory
store, or an Axios caching interceptor) to serve the stored data when a
304 status is returned.