Profiles·Public

axios-retry

semver>=1.0.0postconditions8functions7last verified2026-06-23coverage score78%

Postconditions: what we check

  • axiosRetry · axios-retry-config-only
    info
    WhenThis function configures retry behavior but does not throw errors
    ThrowsN/A - Configuration function
    Required 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 unavailablevisibilityvisible
    Sources[1]
  • axios.get/post/put/delete (with retry) · axios-retry-exhausted
    error
    WhenAll retry attempts have been exhausted
    ThrowsAxiosError (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 unavailablevisibilityvisible
    Sources[1]
  • axiosRetry (validateResponse option) · validate-response-overrides-validate-status
    error
    WhenvalidateResponse callback is set in axiosRetry config
    ThrowsN/A — behavioral configuration change, not a throw
    Required 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 datavisibilitysilent
    Sources[2]
  • axiosRetry (POST/PATCH not retried by default) · post-patch-not-retried-by-default
    warning
    WhenaxiosRetry is configured with default retryCondition and caller makes POST or PATCH requests expecting retry behavior
    ThrowsAxiosError (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 performancevisibilitysilent
    Sources[3]
  • axiosRetry (global timeout behavior) · timeout-global-not-per-retry
    warning
    WhenaxiosRetry is configured with a timeout and shouldResetTimeout is not set to true (default false)
    ThrowsAxiosError 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
    Sources[2][3]
  • axiosRetry (onRetry async error swallowing) · on-retry-error-replaces-original-error
    warning
    WhenonRetry callback throws an error (e.g., token refresh rejects)
    ThrowsError 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 failurevisibilitysilent
    Sources[3]
  • axiosRetry (onRetry async error swallowing) · retry-condition-error-swallowed
    warning
    WhenretryCondition callback throws (e.g., error in custom retry logic)
    ThrowsN/A — error is silently swallowed, retry returns false
    Required 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 performancevisibilitysilent
    Sources[3]
  • axiosRetry (onMaxRetryTimesExceeded async error swallowing) · on-max-retry-times-exceeded-error-replaces-original-error
    warning
    WhenonMaxRetryTimesExceeded callback throws an error (e.g., alerting fails, fallback rejects, logging service unreachable)
    ThrowsError 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[3][4]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Source code
Changelog & releases

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

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

Custom Retry Conditions

onMaxRetryTimesExceeded Callback


Configuration Options

Core Options

  • retries (Number, default: 3): Maximum retry attempts
  • retryDelay (Function): Delay strategy between retries
    • axiosRetry.noDelay() - No delay
    • axiosRetry.exponentialDelay(retryCount, error, initialDelay) - Exponential backoff
    • axiosRetry.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

client.get('/test', {
  'axios-retry': {
    retries: 0  // Disable retries for this request
  }
})

Security Analysis

axios-retry Package

axios Dependency Vulnerabilities

  • Source: https://security.snyk.io/package/npm/axios
  • Known Issues:
    1. SSRF and credential leakage when passing absolute URLs
    2. 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 shouldResetTimeout is 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

Status Code Handling

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

onRetry: async (retryCount, error, requestConfig) => {
  if (error.response?.status === 401) {
    await refreshToken();
  }
}

Rate Limiting with Retry-After

Exponential Backoff with Initial Delay

retryDelay: (retryCount, error) =>
  axiosRetry.exponentialDelay(retryCount, error, 1000)

Nark profile Implications

What Errors Occur

  1. After retries exhausted: axios-retry re-throws the final error
  2. Error types: Same as underlying axios errors (network, HTTP status, timeouts)
  3. 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 onMaxRetryTimesExceeded for graceful failure handling
  • Optional: Use onRetry for 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+)

Issue #282: onMaxRetryTimesExceeded not triggered


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)

Need a different package?
Request a profile