{"record":{"id":"31a7b43c99fe495f","repo":"softonic/axios-retry","slug":"err-canceled","errorCode":"ERR_CANCELED","errorMessage":"ERR_CANCELED","messagePattern":"ERR_CANCELED","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/index.ts:104","lineNumber":96,"sourceCode":"  isNetworkError(error: AxiosError): boolean;\n  isRetryableError(error: AxiosError): boolean;\n  isSafeRequestError(error: AxiosError): boolean;\n  isIdempotentRequestError(error: AxiosError): boolean;\n  isNetworkOrIdempotentRequestError(error: AxiosError): boolean;\n  exponentialDelay(retryCount?: number, error?: AxiosError, delayFactor?: number): number;\n  linearDelay(delayFactor?: number): (retryCount: number, error: AxiosError | undefined) => number;\n}\n\ndeclare module 'axios' {\n  export interface AxiosRequestConfig {\n    'axios-retry'?: IAxiosRetryConfigExtended;\n  }\n}\n\nexport const namespace = 'axios-retry';\n\nexport function isNetworkError(error) {\n  const CODE_EXCLUDE_LIST = ['ERR_CANCELED', 'ECONNABORTED'];\n  if (error.response) {\n    return false;\n  }\n  if (!error.code) {\n    return false;\n  }\n  // Prevents retrying timed out & cancelled requests\n  if (CODE_EXCLUDE_LIST.includes(error.code)) {\n    return false;\n  }\n  // Prevents retrying unsafe errors\n  return isRetryAllowed(error);\n}\n\nconst SAFE_HTTP_METHODS = ['get', 'head', 'options'];\nconst IDEMPOTENT_HTTP_METHODS = SAFE_HTTP_METHODS.concat(['put', 'delete']);\n\nexport function isRetryableError(error: AxiosError): boolean {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/softonic/axios-retry/blob/dd9b700dfbe51ba2962e70e7822734e3e74613c8/src/index.ts#L78-L114","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nconst data = await axios.get('/api/user', { signal: ctrl.signal });\n// caller aborts via ctrl.abort() on unmount -> uncaught ERR_CANCELED\n\n// after\ntry {\n  const { data } = await axios.get('/api/user', { signal: ctrl.signal });\n} catch (err) {\n  if (axios.isCancel?.(err) || err.code === 'ERR_CANCELED') {\n    // expected: caller (or component unmount) cancelled intentionally\n    return;\n  }\n  throw err; // real error, re-throw\n}","handlingStrategy":"try-catch","validationCode":"// Before issuing the request, confirm the signal has not already been aborted.\nimport { isCancel } from 'axios';\n\nasync function safeGet(url, signal) {\n  if (signal?.aborted) {\n    return undefined; // nothing to do — already cancelled\n  }\n  return axios.get(url, { signal });\n}","typeGuard":"import type { AxiosError } from 'axios';\n\nfunction isCanceledError(error: unknown): error is AxiosError {\n  return (\n    typeof error === 'object' &&\n    error !== null &&\n    (error as AxiosError).code === 'ERR_CANCELED'\n  );\n}","tryCatchPattern":"try {\n  await client.get('/api/user', { signal: ctrl.signal });\n} catch (err) {\n  // ERR_CANCELED is intentional control flow, not a failure.\n  if (err?.code === 'ERR_CANCELED' || axios.isCancel?.(err)) return;\n  throw err;\n}","preventionTips":["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."],"tags":["network","cancellation","axios","abortcontroller"],"analyzedSha":"dd9b700dfbe51ba2962e70e7822734e3e74613c8","analyzedAt":"2026-08-07T04:35:39.629Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}