npm-axios

Description
Promise based HTTP client for the browser and node.js
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-axios@0.30.0

error-handling.md docs/

1
# Error Handling and Cancellation
2
3
Comprehensive 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.
4
5
## Capabilities
6
7
### AxiosError Class
8
9
Standard error class providing detailed information about failed HTTP requests.
10
11
```javascript { .api }
12
/**
13
* Axios-specific error class with detailed context
14
*/
15
class AxiosError<T = unknown, D = any> extends Error {
16
constructor(
17
message?: string,
18
code?: string,
19
config?: AxiosRequestConfig<D>,
20
request?: any,
21
response?: AxiosResponse<T, D>
22
);
23
24
/** Request configuration that caused the error */
25
config?: AxiosRequestConfig<D>;
26
/** Error code identifying the type of error */
27
code?: string;
28
/** Platform-specific request object */
29
request?: any;
30
/** Response object (if request completed) */
31
response?: AxiosResponse<T, D>;
32
/** Always true for AxiosError instances */
33
isAxiosError: boolean;
34
/** HTTP status code (if available) */
35
status?: number;
36
/** Serialize error to JSON */
37
toJSON(): object;
38
/** Underlying error cause */
39
cause?: Error;
40
}
41
```
42
43
**Usage Examples:**
44
45
```javascript
46
import axios, { AxiosError } from 'axios';
47
48
try {
49
const response = await axios.get('https://api.example.com/users/123');
50
} catch (error) {
51
if (axios.isAxiosError(error)) {
52
console.log('Request failed:', error.message);
53
console.log('Error code:', error.code);
54
console.log('Status code:', error.response?.status);
55
console.log('Response data:', error.response?.data);
56
console.log('Request config:', error.config);
57
58
// Handle different error types
59
if (error.response) {
60
// Server responded with error status
61
console.log('Server error:', error.response.status);
62
} else if (error.request) {
63
// Request was made but no response received
64
console.log('Network error: No response received');
65
} else {
66
// Request setup error
67
console.log('Request setup error:', error.message);
68
}
69
} else {
70
// Non-Axios error
71
console.log('Unexpected error:', error);
72
}
73
}
74
```
75
76
### Error Codes
77
78
Predefined error codes for common failure scenarios.
79
80
```javascript { .api }
81
// Network and connection errors
82
AxiosError.ERR_NETWORK = "ERR_NETWORK";
83
AxiosError.ECONNABORTED = "ECONNABORTED";
84
AxiosError.ETIMEDOUT = "ETIMEDOUT";
85
86
// Response errors
87
AxiosError.ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE";
88
AxiosError.ERR_BAD_REQUEST = "ERR_BAD_REQUEST";
89
90
// Configuration errors
91
AxiosError.ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE";
92
AxiosError.ERR_BAD_OPTION = "ERR_BAD_OPTION";
93
AxiosError.ERR_INVALID_URL = "ERR_INVALID_URL";
94
95
// Feature support errors
96
AxiosError.ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";
97
AxiosError.ERR_DEPRECATED = "ERR_DEPRECATED";
98
99
// Redirect errors
100
AxiosError.ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS";
101
102
// Cancellation errors
103
AxiosError.ERR_CANCELED = "ERR_CANCELED";
104
```
105
106
**Usage Examples:**
107
108
```javascript
109
try {
110
const response = await axios.get('https://api.example.com/data', {
111
timeout: 5000
112
});
113
} catch (error) {
114
if (axios.isAxiosError(error)) {
115
switch (error.code) {
116
case AxiosError.ETIMEDOUT:
117
console.log('Request timed out');
118
break;
119
case AxiosError.ERR_NETWORK:
120
console.log('Network connection failed');
121
break;
122
case AxiosError.ERR_CANCELED:
123
console.log('Request was cancelled');
124
break;
125
case AxiosError.ERR_BAD_REQUEST:
126
console.log('Invalid request configuration');
127
break;
128
default:
129
console.log('Other error:', error.code);
130
}
131
}
132
}
133
```
134
135
### Error Type Checking
136
137
Utility functions to identify specific error types.
138
139
```javascript { .api }
140
/**
141
* Check if error is an AxiosError
142
* @param payload - Value to check
143
* @returns true if payload is an AxiosError
144
*/
145
axios.isAxiosError(payload: any): payload is AxiosError;
146
147
/**
148
* Check if error is a cancellation error
149
* @param value - Value to check
150
* @returns true if value represents a cancelled request
151
*/
152
axios.isCancel(value: any): boolean;
153
```
154
155
**Usage Examples:**
156
157
```javascript
158
try {
159
const response = await axios.get('/api/data');
160
} catch (error) {
161
if (axios.isAxiosError(error)) {
162
console.log('Axios-specific error');
163
164
if (axios.isCancel(error)) {
165
console.log('Request was cancelled');
166
} else if (error.response) {
167
console.log('HTTP error:', error.response.status);
168
} else {
169
console.log('Network or setup error');
170
}
171
} else {
172
console.log('Non-HTTP error:', error);
173
}
174
}
175
```
176
177
### AbortController Cancellation (Modern)
178
179
Modern request cancellation using the standard AbortController API.
180
181
```javascript { .api }
182
/**
183
* Use AbortController signal for request cancellation
184
*/
185
interface AxiosRequestConfig {
186
signal?: AbortSignal;
187
}
188
```
189
190
**Usage Examples:**
191
192
```javascript
193
// Basic cancellation
194
const controller = new AbortController();
195
196
const promise = axios.get('https://api.example.com/data', {
197
signal: controller.signal
198
});
199
200
// Cancel the request
201
controller.abort();
202
203
try {
204
const response = await promise;
205
} catch (error) {
206
if (axios.isCancel(error)) {
207
console.log('Request cancelled');
208
}
209
}
210
211
// Timeout-based cancellation
212
const controller = new AbortController();
213
214
// Auto-cancel after 5 seconds
215
setTimeout(() => {
216
controller.abort();
217
}, 5000);
218
219
const response = await axios.get('/slow-endpoint', {
220
signal: controller.signal
221
});
222
223
// Cancellation with reason
224
const controller = new AbortController();
225
const response = axios.get('/api/data', {
226
signal: controller.signal
227
});
228
229
// Cancel with custom reason
230
controller.abort('User requested cancellation');
231
```
232
233
### CancelToken Cancellation (Legacy)
234
235
Legacy cancellation mechanism using axios-specific CancelToken.
236
237
```javascript { .api }
238
/**
239
* CancelToken class for request cancellation
240
*/
241
class CancelToken {
242
constructor(executor: (cancel: Canceler) => void);
243
244
/** Promise that resolves when token is cancelled */
245
promise: Promise<Cancel>;
246
/** Cancel reason (if cancelled) */
247
reason?: Cancel;
248
/** Throw error if already cancelled */
249
throwIfRequested(): void;
250
251
/** Create a cancel token source */
252
static source(): CancelTokenSource;
253
}
254
255
interface CancelTokenSource {
256
/** The cancellation token */
257
token: CancelToken;
258
/** Function to cancel the token */
259
cancel: Canceler;
260
}
261
262
interface Canceler {
263
(message?: string, config?: AxiosRequestConfig, request?: any): void;
264
}
265
266
interface Cancel {
267
message: string | undefined;
268
}
269
```
270
271
**Usage Examples:**
272
273
```javascript
274
// Using CancelToken.source()
275
const source = axios.CancelToken.source();
276
277
const promise = axios.get('/api/data', {
278
cancelToken: source.token
279
});
280
281
// Cancel the request
282
source.cancel('Operation cancelled by user');
283
284
try {
285
const response = await promise;
286
} catch (error) {
287
if (axios.isCancel(error)) {
288
console.log('Cancelled:', error.message);
289
}
290
}
291
292
// Using CancelToken constructor
293
let cancel;
294
295
const promise = axios.get('/api/data', {
296
cancelToken: new axios.CancelToken((canceler) => {
297
cancel = canceler;
298
})
299
});
300
301
// Cancel later
302
cancel('User changed their mind');
303
304
// Multiple requests with same token
305
const source = axios.CancelToken.source();
306
307
const promises = [
308
axios.get('/api/users', { cancelToken: source.token }),
309
axios.get('/api/posts', { cancelToken: source.token }),
310
axios.get('/api/comments', { cancelToken: source.token })
311
];
312
313
// Cancel all requests at once
314
source.cancel('Bulk cancellation');
315
316
try {
317
const results = await Promise.allSettled(promises);
318
results.forEach((result, index) => {
319
if (result.status === 'rejected' && axios.isCancel(result.reason)) {
320
console.log(`Request ${index} was cancelled`);
321
}
322
});
323
} catch (error) {
324
// Handle any non-cancellation errors
325
}
326
```
327
328
### CanceledError Class
329
330
Specific error type for cancelled requests.
331
332
```javascript { .api }
333
/**
334
* Error thrown when request is cancelled
335
*/
336
class CanceledError<T> extends AxiosError<T> {
337
// Inherits all AxiosError properties and methods
338
}
339
340
// Backward compatibility alias
341
axios.Cancel = axios.CanceledError;
342
```
343
344
**Usage Examples:**
345
346
```javascript
347
const source = axios.CancelToken.source();
348
349
try {
350
const response = await axios.get('/api/data', {
351
cancelToken: source.token
352
});
353
} catch (error) {
354
if (error instanceof axios.CanceledError) {
355
console.log('Request was cancelled:', error.message);
356
} else if (axios.isAxiosError(error)) {
357
console.log('Other axios error:', error.code);
358
}
359
}
360
361
source.cancel('User cancelled');
362
```
363
364
## Advanced Error Handling Patterns
365
366
### Global Error Handling
367
368
Set up global error handling using response interceptors:
369
370
```javascript
371
// Global error handler
372
axios.interceptors.response.use(
373
(response) => response,
374
(error) => {
375
// Log all errors
376
console.error('API Error:', {
377
url: error.config?.url,
378
method: error.config?.method,
379
status: error.response?.status,
380
message: error.message
381
});
382
383
// Handle specific error types globally
384
if (error.response?.status === 401) {
385
// Redirect to login
386
window.location.href = '/login';
387
} else if (error.response?.status >= 500) {
388
// Show user-friendly error for server errors
389
showErrorToast('Server error. Please try again later.');
390
}
391
392
return Promise.reject(error);
393
}
394
);
395
```
396
397
### Retry Logic with Error Classification
398
399
Implement automatic retry for recoverable errors:
400
401
```javascript
402
const retryableErrors = [
403
AxiosError.ERR_NETWORK,
404
AxiosError.ETIMEDOUT,
405
AxiosError.ECONNABORTED
406
];
407
408
axios.interceptors.response.use(
409
(response) => response,
410
async (error) => {
411
const config = error.config;
412
413
// Don't retry if max attempts reached
414
if (!config || config.__retries >= 3) {
415
return Promise.reject(error);
416
}
417
418
// Only retry specific error types
419
const shouldRetry = retryableErrors.includes(error.code) ||
420
(error.response && error.response.status >= 500);
421
422
if (shouldRetry) {
423
config.__retries = (config.__retries || 0) + 1;
424
425
// Exponential backoff
426
const delay = Math.pow(2, config.__retries) * 1000;
427
await new Promise(resolve => setTimeout(resolve, delay));
428
429
return axios(config);
430
}
431
432
return Promise.reject(error);
433
}
434
);
435
```
436
437
### Request Timeout with Cancellation
438
439
Combine timeout configuration with manual cancellation:
440
441
```javascript
442
async function fetchWithTimeout(url, timeoutMs = 5000) {
443
const controller = new AbortController();
444
445
// Set up timeout
446
const timeoutId = setTimeout(() => {
447
controller.abort();
448
}, timeoutMs);
449
450
try {
451
const response = await axios.get(url, {
452
signal: controller.signal,
453
timeout: timeoutMs * 1.5 // Axios timeout as fallback
454
});
455
456
clearTimeout(timeoutId);
457
return response;
458
} catch (error) {
459
clearTimeout(timeoutId);
460
461
if (axios.isCancel(error)) {
462
throw new Error(`Request timed out after ${timeoutMs}ms`);
463
}
464
throw error;
465
}
466
}
467
468
// Usage
469
try {
470
const response = await fetchWithTimeout('/api/slow-data', 3000);
471
} catch (error) {
472
console.log('Request failed or timed out:', error.message);
473
}
474
```
475
476
### Error Context Enhancement
477
478
Add additional context to errors for better debugging:
479
480
```javascript
481
// Request interceptor to add context
482
axios.interceptors.request.use((config) => {
483
config.metadata = {
484
startTime: Date.now(),
485
requestId: Math.random().toString(36).substr(2, 9)
486
};
487
return config;
488
});
489
490
// Response interceptor to enhance errors
491
axios.interceptors.response.use(
492
(response) => response,
493
(error) => {
494
if (error.config?.metadata) {
495
const duration = Date.now() - error.config.metadata.startTime;
496
497
// Enhance error with additional context
498
error.requestDuration = duration;
499
error.requestId = error.config.metadata.requestId;
500
error.timestamp = new Date().toISOString();
501
}
502
503
return Promise.reject(error);
504
}
505
);
506
```