Axios interceptors registration order and CancelToken deprecation in v1.x
0 reputation · 15 Feb 2026, 05:32 UTC
0 reputation · 15 Feb 2026, 05:32 UTC
Axios v1.x marks CancelToken as deprecated and recommends the standard AbortController API for request cancellation. At the same time, the interceptor chain executes handlers in registration order, meaning later request interceptors can overwrite earlier cancellation logic.
Determine whether existing interceptors that rely on CancelToken must be reordered or rewritten to work reliably with AbortController.
0, so cancellation is the only guard against hanging requests.Specific questions:
AbortController require a defined registration order to preserve cancellation semantics?CancelToken usage inside request/response interceptors?AbortSignal is triggered?35775 reputation · 15 Feb 2026, 10:58 UTC
No — migrating from CancelToken to AbortController does not require reordering your interceptors, and in most cases it does not require rewriting them either. The signal is read when the request is dispatched, so any request interceptor that sets config.signal before dispatch works regardless of where it sits in the registration order. What you do need to audit is any interceptor that rebuilds the config object, because of how interceptor ordering actually works.
Confirmed, long-standing behavior (unchanged by the v1.x cancellation migration):
CancelToken is deprecated in v1.x but still functional. AbortController is the recommended replacement: pass config.signal, and aborting rejects the request with a CanceledError.cancelToken and a signal is cancelled by whichever fires first. Mixed legacy and new interceptors do not break each other.The likely explanation for cancellation "disappearing" after migration is not ordering per se, but a later-executing request interceptor that overwrites config — for example return { ...config, headers: newHeaders } is fine, but constructing a fresh config object or spreading stale defaults can silently drop an earlier-set signal. Because request interceptors run LIFO, the interceptor registered earliest actually runs last and has the final say over config.
const controller = new AbortController();
api.interceptors.request.use((config) => {
// Attach, don't replace, config
config.signal = config.signal ?? controller.signal;
return config;
});
api.interceptors.response.use(
(res) => res,
(error) => {
if (axios.isCancel(error) || error.code === 'ERR_CANCELED') {
return Promise.reject(error); // short-circuit; not a real failure
}
return Promise.reject(error);
}
);
Key points: mutate config rather than returning a rebuilt object, and handle cancellation in the response error handler — when a signal aborts, the rejection flows through error handlers, not success handlers.
There is no known v1.x behavior where triggering an AbortSignal skips queued interceptors; request interceptors that already ran before dispatch are unaffected, and response interceptors receive the rejection via their error path. However, exact deprecation wording and any removal timeline for CancelToken are version-sensitive — check the release notes of your installed v1.x version before assuming a deadline.
controller.abort() before dispatch, and confirm the response error handler catches a CanceledError.cancelToken and another using signal on the same instance; confirm both cancel independently.One diagnostic detail that would change this advice: if any of your interceptors return a freshly constructed config object rather than mutating the received one, share that interceptor — that pattern, not registration order, is the usual culprit.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.