axios-retry
>=1.0.0postconditions8functions7last verified2026-06-23coverage score78%Postconditions: what we check
- axiosRetry · axios-retry-config-onlyinfoWhenThis function configures retry behavior but does not throw errorsThrows
N/A - Configuration functionRequired handlingaxios-retry() is a configuration function that does not throw. The actual error handling requirements are for the UNDERLYING AXIOS METHODS. After retries are exhausted, axios will throw - users must still use try-catch. See the axios Nark profile for specific error handling requirements.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - axios.get/post/put/delete (with retry) · axios-retry-exhaustederrorWhenAll retry attempts have been exhaustedThrows
AxiosError (same as standard axios)Required handlingCaller MUST wrap axios calls in try-catch block even when axios-retry is configured. axios-retry only retries failed requests - it does not prevent errors from being thrown. After the final retry fails, the error is re-thrown exactly as axios would throw it. The retry logic is transparent to error handling - try-catch is still required.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - axiosRetry (validateResponse option) · validate-response-overrides-validate-statuserrorWhenvalidateResponse callback is set in axiosRetry configThrows
N/A — behavioral configuration change, not a throwRequired handlingMUST NOT set validateResponse without understanding it overrides axios's validateStatus for ALL requests on that instance. With validateResponse set, axios no longer resolves successful 2xx responses unless validateResponse returns true for them. Callers relying on axios's default behavior (resolve 2xx, reject non-2xx) will have all responses routed to the error interceptor if validateResponse is configured but doesn't explicitly return true for 2xx status codes. Pattern to avoid (breaks all responses): axiosRetry(instance, { validateResponse: (res) => res.status !== 429 // 200-OK also goes through error path! }); Correct pattern: axiosRetry(instance, { validateResponse: (res) => res.status >= 200 && res.status < 300 });costhighin prodsilent failureusers seelost datavisibilitysilentSources[2] - axiosRetry (POST/PATCH not retried by default) · post-patch-not-retried-by-defaultwarningWhenaxiosRetry is configured with default retryCondition and caller makes POST or PATCH requests expecting retry behaviorThrows
AxiosError (thrown on first failure, no retries attempted)Required handlingMUST explicitly configure retryCondition to retry POST/PATCH if that is the intent. The default retryCondition (isNetworkOrIdempotentRequestError) NEVER retries POST or PATCH — not on network errors, not on 5xx errors. This is intentional (POST is not idempotent — retrying can cause duplicate records), but developers often misconfigure axiosRetry globally and assume POST requests are covered. To retry POST on network errors only (safe for idempotent backends): axiosRetry(instance, { retryCondition: (error) => { return axiosRetry.isNetworkError(error); // Network-only, not 5xx } }); To retry POST on any error (requires idempotent backend): axiosRetry(instance, { retryCondition: axiosRetry.isRetryableError // 5xx + network });costmediumin proddegraded serviceusers seedegraded performancevisibilitysilentSources[3] - axiosRetry (global timeout behavior) · timeout-global-not-per-retrywarningWhenaxiosRetry is configured with a timeout and shouldResetTimeout is not set to true (default false)Throws
AxiosError with code ECONNABORTED (when global timeout expires)Required handlingMUST set shouldResetTimeout: true if you want each retry attempt to have the full timeout budget. Without it, retries on slow servers will exhaust the timeout before all retries run. Example where retries never help (timeout too tight): axios.defaults.timeout = 3000; // 3 second timeout axiosRetry(axios, { retries: 3 }); // First attempt takes 2.8s → only 0.2s left for 3 retries → immediate timeout Correct pattern for retry with full timeout per attempt: axiosRetry(axios, { retries: 3, shouldResetTimeout: true, // Each attempt gets full 3s timeout retryDelay: axiosRetry.exponentialDelay }); This behavioral change was introduced in v3.0.0 (2017-08-13) as a deliberate design decision to prevent retries from extending beyond the intended timeout.costmediumin proddegraded serviceusers seedegraded performancevisibilitysilent - axiosRetry (onRetry async error swallowing) · on-retry-error-replaces-original-errorwarningWhenonRetry callback throws an error (e.g., token refresh rejects)Throws
Error thrown by onRetry callback (replaces original AxiosError)Required handlingonRetry callbacks MUST handle their own errors. If onRetry throws, the error propagated to the catch block is the onRetry error (not the original request AxiosError). This makes error diagnosis difficult. Token refresh pattern that silently loses original error: axiosRetry(instance, { onRetry: async (retryCount, error, config) => { if (error.response?.status === 401) { const token = await refreshToken(); // If this throws, original error is lost config.headers.Authorization = Bearer ${token}; } } }); Correct pattern with error preservation: axiosRetry(instance, { onRetry: async (retryCount, error, config) => { try { if (error.response?.status === 401) { const token = await refreshToken(); config.headers.Authorization = Bearer ${token}; } } catch (refreshError) { console.error('Token refresh failed:', refreshError); // Re-throw to abort retries, or handle silently to continue throw refreshError; } } });costmediumin prodsilent failureusers seeauthentication failurevisibilitysilentSources[3] - axiosRetry (onRetry async error swallowing) · retry-condition-error-swallowedwarningWhenretryCondition callback throws (e.g., error in custom retry logic)Throws
N/A — error is silently swallowed, retry returns falseRequired handlingCustom retryCondition callbacks that throw have their errors silently discarded. The error is caught, returning false (no retry). This means broken retryCondition logic causes silent retry disabling with no log. Broken retryCondition (error silently swallowed): axiosRetry(instance, { retryCondition: (error) => { return someUndefinedHelper.check(error); // TypeError swallowed silently // Result: retries disabled, no indication why } }); MUST test retryCondition logic thoroughly — errors in it disable retries silently in production.costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[3] - axiosRetry (onMaxRetryTimesExceeded async error swallowing) · on-max-retry-times-exceeded-error-replaces-original-errorwarningWhenonMaxRetryTimesExceeded callback throws an error (e.g., alerting fails, fallback rejects, logging service unreachable)Throws
Error thrown by onMaxRetryTimesExceeded callback (replaces original AxiosError)Required handlingonMaxRetryTimesExceeded callbacks MUST handle their own errors internally via try-catch. If they throw, the error reaching the caller's catch block is the callback error — NOT the original retry-exhausted AxiosError. This silently destroys the failure diagnostic ("the API returned 500 three times" becomes "alerting service rejected"). Anti-pattern that swallows the real failure cause: axiosRetry(instance, { retries: 3, onMaxRetryTimesExceeded: async (error, retryCount) => { await alertingService.notify(error); // If this throws, caller sees alerting error await fallbackDb.write({ failed: true }); // Same hazard } }); Correct pattern — preserve original error context: axiosRetry(instance, { retries: 3, onMaxRetryTimesExceeded: async (error, retryCount) => { try { await alertingService.notify(error); await fallbackDb.write({ failed: true }); } catch (sideEffectError) { console.error('Side-effect failed during max-retry handler:', sideEffectError); // Do NOT re-throw — preserves the original AxiosError for the caller } } }); Operational consequence: production incident triage sees the alerting error first and walks the wrong call tree. The 503 from upstream is invisible until log archaeology surfaces the original interceptor trace.costmediumin prodsilent failureusers seedegraded performancevisibilitysilent
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
- [1]github.com/softonic/axios-retrysoftonic/axios-retry
- [3]github.com/softonic/axios-retrysoftonic/axios-retry
- [4]github.com/softonic/axios-retry/blobsoftonic/axios-retry · index.ts
- [2]github.com/softonic/axios-retry/blobsoftonic/axios-retry · CHANGELOG.md
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: axios-retry
This document lists all sources used to create the Nark profile for axios-retry.
Last Updated: 2026-02-27
Official Documentation
Primary Repository
- URL: https://github.com/softonic/axios-retry
- Type: GitHub Repository (Official)
- Relevance: HIGH - Primary source for API documentation and usage patterns
- Key Information:
- Core API:
axiosRetry(axiosInstance, options) - Configuration options: retries, retryDelay, retryCondition, onRetry, onMaxRetryTimesExceeded
- Built-in delay strategies: noDelay, exponentialDelay, linearDelay
- Default retry behavior: network errors and 5xx for idempotent requests only
- Request-specific configuration support
- Core API:
npm Package Page
- URL: https://www.npmjs.com/package/axios-retry
- Type: npm Registry
- Relevance: HIGH - Official package information and download statistics
- Key Information:
- 5.5M+ weekly downloads
- Maintained by Softonic
- No major security vulnerabilities in package itself
Error Handling Patterns
Default Retry Behavior
- Source: https://github.com/softonic/axios-retry/blob/master/README.md
- Pattern: By default, only retries:
- Network errors (ECONNREFUSED, ETIMEDOUT, etc.)
- 5xx errors for idempotent methods (GET, HEAD, OPTIONS, PUT, DELETE)
- NOT retried by default: 4xx errors including 429 (rate limiting), 401 (auth)
Custom Retry Conditions
- Source: https://www.joinplank.com/articles/axios-handling-errors-and-using-retry-mechanisms
- Pattern: Use
retryConditionoption to customize which errors trigger retries - Common Use Case: Retrying 429 (Too Many Requests) with Retry-After header support
onMaxRetryTimesExceeded Callback
- Source: https://github.com/softonic/axios-retry/blob/master/CHANGELOG.md
- Purpose: Handle final failure after all retries exhausted
- Signature:
(error: AxiosError, count: number) => void - Common Use Cases:
- Logging final failures
- Triggering logout on auth failures
- Implementing fallback strategies
- User notification
Configuration Options
Core Options
- retries (Number, default: 3): Maximum retry attempts
- retryDelay (Function): Delay strategy between retries
axiosRetry.noDelay()- No delayaxiosRetry.exponentialDelay(retryCount, error, initialDelay)- Exponential backoffaxiosRetry.linearDelay()- Linear delay- Custom function:
(retryCount, error) => milliseconds
- retryCondition (Function, default:
isNetworkOrIdempotentRequestError): Determines if error should trigger retry - shouldResetTimeout (Boolean, default: false): Reset timeout between retries
- onRetry (Function): Callback before each retry -
(retryCount, error, requestConfig) => void - onMaxRetryTimesExceeded (Function): Callback after final failure -
(error, count) => void - validateResponse (Function/null, default: null): Custom response validation
Request-Specific Override
- Source: https://github.com/softonic/axios-retry
- Pattern: Override defaults per request using
axios-retryconfig key
client.get('/test', {
'axios-retry': {
retries: 0 // Disable retries for this request
}
})
Security Analysis
axios-retry Package
- Source: https://security.snyk.io/package/npm/axios-retry
- Status: No direct CVEs reported
- Maintenance Concern: No new releases in past 12 months (as of 2026-02)
- Dependencies: Relies on axios (which has had security issues)
axios Dependency Vulnerabilities
- Source: https://security.snyk.io/package/npm/axios
- Known Issues:
- SSRF and credential leakage when passing absolute URLs
- DoS vulnerability in Node.js with data: scheme URLs (fixed in axios 0.30.2 and 1.12.0)
- Recommendation: Ensure axios dependency is up-to-date
Common Mistakes and Best Practices
Timeout Configuration
- Source: https://github.com/softonic/axios-retry
- Mistake: Not understanding global vs per-retry timeout
- Best Practice: "Unless
shouldResetTimeoutis set, the plugin interprets the request timeout as a global value, so it is not used for each retry but for the whole request lifecycle"
Infinite Retry Loops
- Source: https://www.zenrows.com/blog/axios-retry
- Mistake: Not setting a maximum retry limit
- Best Practice: Always configure
retriesparameter to prevent infinite loops
Status Code Handling
- Source: https://www.joinplank.com/articles/axios-handling-errors-and-using-retry-mechanisms
- Mistake: Expecting 4xx errors to retry automatically
- Best Practice: Use
retryConditionto explicitly handle status codes like 429
Error Propagation
- Source: https://axios-http.com/docs/handling_errors
- Mistake: Not wrapping axios calls in try-catch when retries are exhausted
- Best Practice: After all retries fail, axios will throw - always use try-catch for final error handling
Real-World Usage Patterns
Token Refresh on 401
- Source: https://github.com/softonic/axios-retry/issues
- Pattern: Use
onRetrycallback for async operations like token refresh
onRetry: async (retryCount, error, requestConfig) => {
if (error.response?.status === 401) {
await refreshToken();
}
}
Rate Limiting with Retry-After
- Source: https://github.com/softonic/axios-retry
- Pattern: Library automatically respects HTTP Retry-After header
- Behavior: Uses whichever is greater: header value or configured
retryDelay
Exponential Backoff with Initial Delay
- Source: https://iproyal.com/blog/axios-retry-requests/
- Pattern: Custom delay with initial value
retryDelay: (retryCount, error) =>
axiosRetry.exponentialDelay(retryCount, error, 1000)
Nark profile Implications
What Errors Occur
- After retries exhausted: axios-retry re-throws the final error
- Error types: Same as underlying axios errors (network, HTTP status, timeouts)
- No new error types: axios-retry doesn't introduce new error classes
Error Handling Requirements
- Required: try-catch around axios calls (axios-retry doesn't prevent final throw)
- Recommended: Implement
onMaxRetryTimesExceededfor graceful failure handling - Optional: Use
onRetryfor side effects between attempts
Functions That Throw
axiosRetry()itself doesn't throw - it's a configuration function- The underlying axios methods (get, post, etc.) will still throw after retries fail
- No behavioral change in error throwing - axios-retry is transparent
Known Issues and Behavior Changes
Issue #240: retryCondition not called on 401 (v3.2.0+)
- Source: https://github.com/softonic/axios-retry/issues/240
- Impact: Breaking change in v3.2.0
- Workaround: Documented in issue thread
Issue #282: onMaxRetryTimesExceeded not triggered
- Source: https://github.com/softonic/axios-retry/issues/282
- Status: Open issue
- Impact: Callback may not fire in certain scenarios
Summary
axios-retry is a configuration library that modifies axios behavior but does not change error throwing patterns. After retries are exhausted, axios-retry re-throws the final error exactly as axios would. Therefore:
- ✅ Same postconditions as axios apply
- ✅ try-catch still required around axios HTTP methods
- ✅ Error handling covered by axios contract
Recommendation: This package does not require a separate Nark profile. Users should refer to the axios contract for error handling requirements. The axios-retry library only adds retry logic before the final error is thrown.
Total Sources: 15+ URLs consulted Research Date: 2026-02-27 Researched By: Claude AI (claude-agent-1)