softonic/axios-retry · warning
ERR_CANCELED
ERR_CANCELED
Error message
ERR_CANCELED
What it means
ERR_CANCELED is set by axios (not by axios-retry) on the rejected error when an in-flight request is aborted via an AbortController/AbortSignal (or a CancelToken in older axios). At src/index.ts:96 axios-retry places 'ERR_CANCELED' in CODE_EXCLUDE_LIST inside isNetworkError, so a canceled request is explicitly NOT classified as a network error and is therefore NOT retried by the default retryCondition. The rationale (see the inline comment 'Prevents retrying timed out & cancelled requests' at src/index.ts:103) is that cancellation represents deliberate user intent, not a transient failure worth retrying.
Source
Thrown at src/index.ts:104:96
isNetworkError(error: AxiosError): boolean;
isRetryableError(error: AxiosError): boolean;
isSafeRequestError(error: AxiosError): boolean;
isIdempotentRequestError(error: AxiosError): boolean;
isNetworkOrIdempotentRequestError(error: AxiosError): boolean;
exponentialDelay(retryCount?: number, error?: AxiosError, delayFactor?: number): number;
linearDelay(delayFactor?: number): (retryCount: number, error: AxiosError | undefined) => number;
}
declare module 'axios' {
export interface AxiosRequestConfig {
'axios-retry'?: IAxiosRetryConfigExtended;
}
}
export const namespace = 'axios-retry';
export function isNetworkError(error) {
const CODE_EXCLUDE_LIST = ['ERR_CANCELED', 'ECONNABORTED'];
if (error.response) {
return false;
}
if (!error.code) {
return false;
}
// Prevents retrying timed out & cancelled requests
if (CODE_EXCLUDE_LIST.includes(error.code)) {
return false;
}
// Prevents retrying unsafe errors
return isRetryAllowed(error);
}
const SAFE_HTTP_METHODS = ['get', 'head', 'options'];
const IDEMPOTENT_HTTP_METHODS = SAFE_HTTP_METHODS.concat(['put', 'delete']);
export function isRetryableError(error: AxiosError): boolean {View on GitHub (pinned to dd9b700dfb)
Solutions
- If the cancel was intentional, treat ERR_CANCELED as expected control flow: catch it and swallow/ignore it rather than surfacing it as an error to the user.
- If you DO want canceled requests to be retried, supply a custom retryCondition that returns true for error.code === 'ERR_CANCELED' in the appropriate context (e.g. only when the abort was not user-initiated).
- Make sure you are not aborting a shared AbortController unintentionally — give each in-flight request its own controller unless you genuinely mean to cancel a whole batch.
- Do not reuse the same AbortController across retries: axios-retry forwards config.signal into each retry (src/index.ts:273-289), so aborting between retries short-circuits the retry loop.
- Verify no upstream interceptor or wrapper is auto-aborting on every response (some logging/cancel plugins do this).
Example fix
// before
const data = await axios.get('/api/user', { signal: ctrl.signal });
// caller aborts via ctrl.abort() on unmount -> uncaught ERR_CANCELED
// after
try {
const { data } = await axios.get('/api/user', { signal: ctrl.signal });
} catch (err) {
if (axios.isCancel?.(err) || err.code === 'ERR_CANCELED') {
// expected: caller (or component unmount) cancelled intentionally
return;
}
throw err; // real error, re-throw
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before issuing the request, confirm the signal has not already been aborted.
import { isCancel } from 'axios';
async function safeGet(url, signal) {
if (signal?.aborted) {
return undefined; // nothing to do — already cancelled
}
return axios.get(url, { signal });
} Type guard
import type { AxiosError } from 'axios';
function isCanceledError(error: unknown): error is AxiosError {
return (
typeof error === 'object' &&
error !== null &&
(error as AxiosError).code === 'ERR_CANCELED'
);
} Try / catch
try {
await client.get('/api/user', { signal: ctrl.signal });
} catch (err) {
// ERR_CANCELED is intentional control flow, not a failure.
if (err?.code === 'ERR_CANCELED' || axios.isCancel?.(err)) return;
throw err;
} Prevention
- Give each in-flight request its own AbortController unless you intentionally want to cancel a group.
- Always handle ERR_CANCELED in the catch block of any request that accepts a signal.
- Do not share one AbortController across requests you want to retry independently.
- When migrating from CancelToken to AbortController, update isCancel checks to also test code === 'ERR_CANCELED'.
- Confirm no upstream interceptor auto-aborts every response.
When it happens
Trigger: A caller passes signal: abortController.signal in the AxiosRequestConfig of a request, then calls abortController.abort() while the request is still pending. Axios rejects with an AxiosError whose code === 'ERR_CANCELED' and no .response. The axios-retry response interceptor (src/index.ts:311) runs; shouldRetry -> isNetworkOrIdempotentRequestError -> isNetworkError returns false at src/index.ts:104 because the code is in CODE_EXCLUDE_LIST, so no retry is scheduled and the error is re-thrown via Promise.reject at src/index.ts:328.
Common situations: React/Vue/Svelte components aborting fetches on unmount; a debounced search where each new keystroke cancels the previous in-flight request; an AbortController accidentally shared across multiple requests so aborting one cancels siblings; migration from the deprecated axios CancelToken to AbortController; race-condition where a parent caller aborts because a newer request superseded the old one.
Related errors
AI-assisted analysis of softonic/axios-retry@dd9b700dfb (2026-08-07).
Data as JSON: /api/errors/31a7b43c99fe495f.
Report an issue: GitHub.