- Spec files
npm-axios
Describes: pkg:npm/axios@0.30.x
- Description
- Promise based HTTP client for the browser and node.js
- Author
- tessl
- Last updated
error-handling.md docs/
1# Error Handling and Cancellation23Comprehensive error handling with detailed error information and multiple request cancellation mechanisms. Supports both modern AbortController and legacy CancelToken patterns, with rich error context including request/response data.45## Capabilities67### AxiosError Class89Standard error class providing detailed information about failed HTTP requests.1011```javascript { .api }12/**13* Axios-specific error class with detailed context14*/15class AxiosError<T = unknown, D = any> extends Error {16constructor(17message?: string,18code?: string,19config?: AxiosRequestConfig<D>,20request?: any,21response?: AxiosResponse<T, D>22);2324/** Request configuration that caused the error */25config?: AxiosRequestConfig<D>;26/** Error code identifying the type of error */27code?: string;28/** Platform-specific request object */29request?: any;30/** Response object (if request completed) */31response?: AxiosResponse<T, D>;32/** Always true for AxiosError instances */33isAxiosError: boolean;34/** HTTP status code (if available) */35status?: number;36/** Serialize error to JSON */37toJSON(): object;38/** Underlying error cause */39cause?: Error;40}41```4243**Usage Examples:**4445```javascript46import axios, { AxiosError } from 'axios';4748try {49const response = await axios.get('https://api.example.com/users/123');50} catch (error) {51if (axios.isAxiosError(error)) {52console.log('Request failed:', error.message);53console.log('Error code:', error.code);54console.log('Status code:', error.response?.status);55console.log('Response data:', error.response?.data);56console.log('Request config:', error.config);5758// Handle different error types59if (error.response) {60// Server responded with error status61console.log('Server error:', error.response.status);62} else if (error.request) {63// Request was made but no response received64console.log('Network error: No response received');65} else {66// Request setup error67console.log('Request setup error:', error.message);68}69} else {70// Non-Axios error71console.log('Unexpected error:', error);72}73}74```7576### Error Codes7778Predefined error codes for common failure scenarios.7980```javascript { .api }81// Network and connection errors82AxiosError.ERR_NETWORK = "ERR_NETWORK";83AxiosError.ECONNABORTED = "ECONNABORTED";84AxiosError.ETIMEDOUT = "ETIMEDOUT";8586// Response errors87AxiosError.ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE";88AxiosError.ERR_BAD_REQUEST = "ERR_BAD_REQUEST";8990// Configuration errors91AxiosError.ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE";92AxiosError.ERR_BAD_OPTION = "ERR_BAD_OPTION";93AxiosError.ERR_INVALID_URL = "ERR_INVALID_URL";9495// Feature support errors96AxiosError.ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";97AxiosError.ERR_DEPRECATED = "ERR_DEPRECATED";9899// Redirect errors100AxiosError.ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS";101102// Cancellation errors103AxiosError.ERR_CANCELED = "ERR_CANCELED";104```105106**Usage Examples:**107108```javascript109try {110const response = await axios.get('https://api.example.com/data', {111timeout: 5000112});113} catch (error) {114if (axios.isAxiosError(error)) {115switch (error.code) {116case AxiosError.ETIMEDOUT:117console.log('Request timed out');118break;119case AxiosError.ERR_NETWORK:120console.log('Network connection failed');121break;122case AxiosError.ERR_CANCELED:123console.log('Request was cancelled');124break;125case AxiosError.ERR_BAD_REQUEST:126console.log('Invalid request configuration');127break;128default:129console.log('Other error:', error.code);130}131}132}133```134135### Error Type Checking136137Utility functions to identify specific error types.138139```javascript { .api }140/**141* Check if error is an AxiosError142* @param payload - Value to check143* @returns true if payload is an AxiosError144*/145axios.isAxiosError(payload: any): payload is AxiosError;146147/**148* Check if error is a cancellation error149* @param value - Value to check150* @returns true if value represents a cancelled request151*/152axios.isCancel(value: any): boolean;153```154155**Usage Examples:**156157```javascript158try {159const response = await axios.get('/api/data');160} catch (error) {161if (axios.isAxiosError(error)) {162console.log('Axios-specific error');163164if (axios.isCancel(error)) {165console.log('Request was cancelled');166} else if (error.response) {167console.log('HTTP error:', error.response.status);168} else {169console.log('Network or setup error');170}171} else {172console.log('Non-HTTP error:', error);173}174}175```176177### AbortController Cancellation (Modern)178179Modern request cancellation using the standard AbortController API.180181```javascript { .api }182/**183* Use AbortController signal for request cancellation184*/185interface AxiosRequestConfig {186signal?: AbortSignal;187}188```189190**Usage Examples:**191192```javascript193// Basic cancellation194const controller = new AbortController();195196const promise = axios.get('https://api.example.com/data', {197signal: controller.signal198});199200// Cancel the request201controller.abort();202203try {204const response = await promise;205} catch (error) {206if (axios.isCancel(error)) {207console.log('Request cancelled');208}209}210211// Timeout-based cancellation212const controller = new AbortController();213214// Auto-cancel after 5 seconds215setTimeout(() => {216controller.abort();217}, 5000);218219const response = await axios.get('/slow-endpoint', {220signal: controller.signal221});222223// Cancellation with reason224const controller = new AbortController();225const response = axios.get('/api/data', {226signal: controller.signal227});228229// Cancel with custom reason230controller.abort('User requested cancellation');231```232233### CancelToken Cancellation (Legacy)234235Legacy cancellation mechanism using axios-specific CancelToken.236237```javascript { .api }238/**239* CancelToken class for request cancellation240*/241class CancelToken {242constructor(executor: (cancel: Canceler) => void);243244/** Promise that resolves when token is cancelled */245promise: Promise<Cancel>;246/** Cancel reason (if cancelled) */247reason?: Cancel;248/** Throw error if already cancelled */249throwIfRequested(): void;250251/** Create a cancel token source */252static source(): CancelTokenSource;253}254255interface CancelTokenSource {256/** The cancellation token */257token: CancelToken;258/** Function to cancel the token */259cancel: Canceler;260}261262interface Canceler {263(message?: string, config?: AxiosRequestConfig, request?: any): void;264}265266interface Cancel {267message: string | undefined;268}269```270271**Usage Examples:**272273```javascript274// Using CancelToken.source()275const source = axios.CancelToken.source();276277const promise = axios.get('/api/data', {278cancelToken: source.token279});280281// Cancel the request282source.cancel('Operation cancelled by user');283284try {285const response = await promise;286} catch (error) {287if (axios.isCancel(error)) {288console.log('Cancelled:', error.message);289}290}291292// Using CancelToken constructor293let cancel;294295const promise = axios.get('/api/data', {296cancelToken: new axios.CancelToken((canceler) => {297cancel = canceler;298})299});300301// Cancel later302cancel('User changed their mind');303304// Multiple requests with same token305const source = axios.CancelToken.source();306307const promises = [308axios.get('/api/users', { cancelToken: source.token }),309axios.get('/api/posts', { cancelToken: source.token }),310axios.get('/api/comments', { cancelToken: source.token })311];312313// Cancel all requests at once314source.cancel('Bulk cancellation');315316try {317const results = await Promise.allSettled(promises);318results.forEach((result, index) => {319if (result.status === 'rejected' && axios.isCancel(result.reason)) {320console.log(`Request ${index} was cancelled`);321}322});323} catch (error) {324// Handle any non-cancellation errors325}326```327328### CanceledError Class329330Specific error type for cancelled requests.331332```javascript { .api }333/**334* Error thrown when request is cancelled335*/336class CanceledError<T> extends AxiosError<T> {337// Inherits all AxiosError properties and methods338}339340// Backward compatibility alias341axios.Cancel = axios.CanceledError;342```343344**Usage Examples:**345346```javascript347const source = axios.CancelToken.source();348349try {350const response = await axios.get('/api/data', {351cancelToken: source.token352});353} catch (error) {354if (error instanceof axios.CanceledError) {355console.log('Request was cancelled:', error.message);356} else if (axios.isAxiosError(error)) {357console.log('Other axios error:', error.code);358}359}360361source.cancel('User cancelled');362```363364## Advanced Error Handling Patterns365366### Global Error Handling367368Set up global error handling using response interceptors:369370```javascript371// Global error handler372axios.interceptors.response.use(373(response) => response,374(error) => {375// Log all errors376console.error('API Error:', {377url: error.config?.url,378method: error.config?.method,379status: error.response?.status,380message: error.message381});382383// Handle specific error types globally384if (error.response?.status === 401) {385// Redirect to login386window.location.href = '/login';387} else if (error.response?.status >= 500) {388// Show user-friendly error for server errors389showErrorToast('Server error. Please try again later.');390}391392return Promise.reject(error);393}394);395```396397### Retry Logic with Error Classification398399Implement automatic retry for recoverable errors:400401```javascript402const retryableErrors = [403AxiosError.ERR_NETWORK,404AxiosError.ETIMEDOUT,405AxiosError.ECONNABORTED406];407408axios.interceptors.response.use(409(response) => response,410async (error) => {411const config = error.config;412413// Don't retry if max attempts reached414if (!config || config.__retries >= 3) {415return Promise.reject(error);416}417418// Only retry specific error types419const shouldRetry = retryableErrors.includes(error.code) ||420(error.response && error.response.status >= 500);421422if (shouldRetry) {423config.__retries = (config.__retries || 0) + 1;424425// Exponential backoff426const delay = Math.pow(2, config.__retries) * 1000;427await new Promise(resolve => setTimeout(resolve, delay));428429return axios(config);430}431432return Promise.reject(error);433}434);435```436437### Request Timeout with Cancellation438439Combine timeout configuration with manual cancellation:440441```javascript442async function fetchWithTimeout(url, timeoutMs = 5000) {443const controller = new AbortController();444445// Set up timeout446const timeoutId = setTimeout(() => {447controller.abort();448}, timeoutMs);449450try {451const response = await axios.get(url, {452signal: controller.signal,453timeout: timeoutMs * 1.5 // Axios timeout as fallback454});455456clearTimeout(timeoutId);457return response;458} catch (error) {459clearTimeout(timeoutId);460461if (axios.isCancel(error)) {462throw new Error(`Request timed out after ${timeoutMs}ms`);463}464throw error;465}466}467468// Usage469try {470const response = await fetchWithTimeout('/api/slow-data', 3000);471} catch (error) {472console.log('Request failed or timed out:', error.message);473}474```475476### Error Context Enhancement477478Add additional context to errors for better debugging:479480```javascript481// Request interceptor to add context482axios.interceptors.request.use((config) => {483config.metadata = {484startTime: Date.now(),485requestId: Math.random().toString(36).substr(2, 9)486};487return config;488});489490// Response interceptor to enhance errors491axios.interceptors.response.use(492(response) => response,493(error) => {494if (error.config?.metadata) {495const duration = Date.now() - error.config.metadata.startTime;496497// Enhance error with additional context498error.requestDuration = duration;499error.requestId = error.config.metadata.requestId;500error.timestamp = new Date().toISOString();501}502503return Promise.reject(error);504}505);506```