Releases: JustinBeckwith/retry-axios
retry-axios: v4.0.0
4.0.0 (2025-10-20)
⚠ BREAKING CHANGES
This major release includes several breaking changes that simplify the API and improve consistency. Please review the migration guide below for each change.
1. Node.js Version Requirements
This library now requires Node.js 20 or higher. Previous versions supported Node.js 6, 8, 12, and 14, which are all now end-of-life.
Migration Required: Upgrade your Node.js version to 20 or higher before upgrading to retry-axios 4.0.
# Check your Node.js version
node --version
# If below v20, upgrade Node.js first
# Visit https://nodejs.org or use a version manager like nvm2. Removal of config.instance Option
The config.instance option has been removed. The axios instance is now automatically used from the interceptor attachment point.
This was confusing because users had to specify the instance twice - once in raxConfig and once in rax.attach(). Now you only specify it once in rax.attach().
Before (v3.x):
const myAxiosInstance = axios.create();
myAxiosInstance.defaults.raxConfig = {
instance: myAxiosInstance, // ❌ Remove this
retry: 3
};
rax.attach(myAxiosInstance);After (v4.0):
const myAxiosInstance = axios.create();
myAxiosInstance.defaults.raxConfig = {
retry: 3 // ✅ Instance is automatically used from rax.attach()
};
rax.attach(myAxiosInstance);Migration Required: Remove the instance property from your raxConfig objects.
3. Simplified Retry Configuration - Removal of noResponseRetries
The noResponseRetries configuration option has been removed. The retry option now controls the maximum number of retries for ALL error types (both response errors like 5xx and network errors like timeouts).
This simplifies the API to match industry standards. Popular libraries like axios-retry, Got, and Ky all use a single retry count.
Before (v3.x):
raxConfig: {
retry: 3, // For 5xx response errors
noResponseRetries: 2 // For network/timeout errors
}After (v4.0):
raxConfig: {
retry: 3 // For ALL errors (network + response errors)
}If you need different behavior for network errors vs response errors, use the shouldRetry callback:
raxConfig: {
retry: 5,
shouldRetry: (err) => {
const cfg = rax.getConfig(err);
// Network error (no response) - allow up to 5 retries
if (!err.response) {
return cfg.currentRetryAttempt < 5;
}
// Response error (5xx, 429, etc) - limit to 2 retries
return cfg.currentRetryAttempt < 2;
}
}Migration Required:
- If you used
noResponseRetries, remove it and adjust yourretryvalue as needed - If you need different retry counts for different error types, implement a
shouldRetryfunction
4. onRetryAttempt Now Requires Async Functions
The onRetryAttempt callback must now return a Promise. It will be awaited before the retry attempt proceeds. If the Promise is rejected, the retry will be aborted.
Additionally, the timing has changed: onRetryAttempt is now called AFTER the backoff delay (right before the retry), not before. A new onError callback has been added that fires immediately when an error occurs.
Before (v3.x):
raxConfig: {
onRetryAttempt: (err) => {
// Synchronous callback, called before backoff delay
console.log('About to retry');
}
}After (v4.0):
raxConfig: {
// Called immediately when error occurs, before backoff delay
onError: async (err) => {
console.log('Error occurred, will retry after backoff');
},
// Called after backoff delay, before retry attempt
onRetryAttempt: async (err) => {
console.log('About to retry now');
// Can perform async operations like refreshing tokens
const token = await refreshAuthToken();
// If this throws, the retry is aborted
}
}Common use case - Refreshing authentication tokens:
raxConfig: {
retry: 3,
onRetryAttempt: async (err) => {
// Refresh expired token before retrying
if (err.response?.status === 401) {
const newToken = await refreshToken();
// Update the authorization header for the retry
err.config.headers.Authorization = `Bearer ${newToken}`;
}
}
}Migration Required:
- Change
onRetryAttemptto be an async function or return a Promise - If you need immediate error notification (old
onRetryAttempttiming), use the newonErrorcallback instead - If your callback throws or rejects, be aware this will now abort the retry
Summary of All Breaking Changes
- Node.js 20+ required - Drops support for Node.js 6, 8, 12, and 14
- Remove
config.instance- Axios instance is now automatically used fromrax.attach() - Remove
noResponseRetries- Useretryfor all error types, or implementshouldRetryfor custom logic onRetryAttemptmust be async - Must return a Promise, called after backoff delay (useonErrorfor immediate notification)
Features
- accept promises on config.onRetryAttempt (#23) (acfbe39)
- add configurable backoffType (#76) (6794d85)
- Add jitter support and use retryDelay as base for exponential backoff (#314) (7436b59)
- Add retriesRemaining property to track remaining retry attempts (#316) (2d1f46b)
- add support for cjs (#291) (38244be)
- add support for configurable http methods (819855c)
- add support for noResponseRetries (d2cfde7)
- add support for onRetryAttempt handler (fa17de4)
- add support for overriding shouldRetry (76fcff5)
- add support for statusCodesToRetry (9283c9e)
- allow retryDelay to be 0 (#132) (57ba46f)
- Collect all errors in errors array during retry attempts (#315) (a7ae9e1)
- configurable maxRetryDelay (#165) (b8842d7)
- drop support for node.js 6, add 12 (78ea044)
- export the shouldRetryRequest method (#74) (694d638)
- produce es, common, and umd bundles (#107) (62cabf5)
- Remove redundant config.instance option (#312) (402723d)
- ship source maps (#223) (247fae0)
- Simplify retry configuration API (#311) (cb447b3)
- support retry-after header (#142) (5c6cace)
- support the latest versions of node.js (#188) (ef74217)
- umd compatibility with babel 7.x (#21) (f1b336c)
Bug Fixes
v3.2.1
v3.2.0
v3.1.3
v3.1.2
v3.1.1
v3.1.0
v3.0.0
3.0.0 (2022-05-04)
BREAKING CHANGES
- This release drops support for node.js 12 and 14. It also drops support for the browser specific compilation, as the entire toolchain was deprecated. I am open to this being re-added if someone wants to take it on :)