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@1.11.0

error-handling.md docs/

1
# Error Handling
2
3
Structured error handling with detailed error information, error codes, and type checking utilities for robust application error management.
4
5
## Capabilities
6
7
### AxiosError Class
8
9
Main error class extending native Error with detailed context about failed requests.
10
11
```javascript { .api }
12
/**
13
* Axios-specific error with request/response context
14
*/
15
class AxiosError<T = unknown, D = any> extends Error {
16
constructor(
17
message?: string,
18
code?: string,
19
config?: InternalAxiosRequestConfig<D>,
20
request?: any,
21
response?: AxiosResponse<T, D>
22
);
23
24
/** Request configuration that caused the error */
25
config?: InternalAxiosRequestConfig<D>;
26
/** Error code string */
27
code?: string;
28
/** Request object (XMLHttpRequest, IncomingMessage, etc.) */
29
request?: any;
30
/** Response object if server responded */
31
response?: AxiosResponse<T, D>;
32
/** Always true for AxiosError instances */
33
isAxiosError: boolean;
34
/** HTTP status code if available */
35
status?: number;
36
/** Underlying error cause */
37
cause?: Error;
38
39
/** Serialize error to JSON object */
40
toJSON(): object;
41
}
42
```
43
44
**Usage Examples:**
45
46
```javascript
47
import axios from "axios";
48
49
try {
50
const response = await axios.get("https://api.example.com/users");
51
} catch (error) {
52
if (axios.isAxiosError(error)) {
53
console.log("Error message:", error.message);
54
console.log("Error code:", error.code);
55
console.log("Request URL:", error.config?.url);
56
console.log("HTTP status:", error.response?.status);
57
console.log("Response data:", error.response?.data);
58
59
// Serialize for logging
60
console.log("Full error:", error.toJSON());
61
}
62
}
63
```
64
65
### Error Code Constants
66
67
Predefined error codes for common failure scenarios.
68
69
```javascript { .api }
70
// Network and connection errors
71
static readonly ERR_NETWORK = "ERR_NETWORK";
72
static readonly ECONNABORTED = "ECONNABORTED";
73
static readonly ETIMEDOUT = "ETIMEDOUT";
74
75
// Request/Response errors
76
static readonly ERR_BAD_REQUEST = "ERR_BAD_REQUEST";
77
static readonly ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE";
78
79
// Configuration errors
80
static readonly ERR_BAD_OPTION = "ERR_BAD_OPTION";
81
static readonly ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE";
82
83
// Feature/Support errors
84
static readonly ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";
85
static readonly ERR_DEPRECATED = "ERR_DEPRECATED";
86
87
// URL errors
88
static readonly ERR_INVALID_URL = "ERR_INVALID_URL";
89
90
// Cancellation errors
91
static readonly ERR_CANCELED = "ERR_CANCELED";
92
93
// Redirect errors
94
static readonly ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS";
95
```
96
97
**Usage Examples:**
98
99
```javascript
100
try {
101
const response = await axios.get(url, { timeout: 5000 });
102
} catch (error) {
103
if (axios.isAxiosError(error)) {
104
switch (error.code) {
105
case axios.AxiosError.ETIMEDOUT:
106
console.log("Request timed out");
107
break;
108
case axios.AxiosError.ERR_NETWORK:
109
console.log("Network error occurred");
110
break;
111
case axios.AxiosError.ERR_BAD_REQUEST:
112
console.log("Bad request configuration");
113
break;
114
case axios.AxiosError.ERR_CANCELED:
115
console.log("Request was canceled");
116
break;
117
default:
118
console.log("Unknown error:", error.code);
119
}
120
}
121
}
122
```
123
124
### Error Factory Method
125
126
Create AxiosError instances from existing errors.
127
128
```javascript { .api }
129
/**
130
* Create AxiosError from existing error
131
* @param error - Original error object
132
* @param code - Error code to assign
133
* @param config - Request configuration
134
* @param request - Request object
135
* @param response - Response object
136
* @param customProps - Additional properties
137
* @returns New AxiosError instance
138
*/
139
static AxiosError.from<T = unknown, D = any>(
140
error: Error | unknown,
141
code?: string,
142
config?: InternalAxiosRequestConfig<D>,
143
request?: any,
144
response?: AxiosResponse<T, D>,
145
customProps?: object
146
): AxiosError<T, D>;
147
```
148
149
**Usage Examples:**
150
151
```javascript
152
// Convert generic error to AxiosError
153
try {
154
// Some operation that might throw
155
throw new Error("Something went wrong");
156
} catch (originalError) {
157
const axiosError = axios.AxiosError.from(
158
originalError,
159
"CUSTOM_ERROR",
160
config,
161
request,
162
response,
163
{ customProperty: "additional context" }
164
);
165
166
throw axiosError;
167
}
168
```
169
170
### CanceledError Class
171
172
Specific error type for canceled requests.
173
174
```javascript { .api }
175
/**
176
* Error thrown when request is canceled
177
*/
178
class CanceledError<T> extends AxiosError<T> {
179
constructor(message?: string, config?: InternalAxiosRequestConfig, request?: any);
180
}
181
182
// Legacy alias for backward compatibility
183
const Cancel = CanceledError;
184
```
185
186
### Error Type Checking
187
188
Utility functions to identify different types of errors.
189
190
```javascript { .api }
191
/**
192
* Check if error is an AxiosError instance
193
* @param payload - Value to check
194
* @returns True if payload is AxiosError
195
*/
196
axios.isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
197
198
/**
199
* Check if error is due to request cancellation
200
* @param value - Value to check
201
* @returns True if value represents cancellation
202
*/
203
axios.isCancel(value: any): value is Cancel;
204
```
205
206
**Usage Examples:**
207
208
```javascript
209
try {
210
const response = await axios.get(url);
211
} catch (error) {
212
if (axios.isCancel(error)) {
213
console.log("Request was canceled:", error.message);
214
return; // Handle cancellation gracefully
215
}
216
217
if (axios.isAxiosError(error)) {
218
// Handle different HTTP status codes
219
if (error.response) {
220
switch (error.response.status) {
221
case 400:
222
console.log("Bad request:", error.response.data);
223
break;
224
case 401:
225
console.log("Unauthorized - redirect to login");
226
window.location.href = "/login";
227
break;
228
case 403:
229
console.log("Forbidden - insufficient permissions");
230
break;
231
case 404:
232
console.log("Resource not found");
233
break;
234
case 429:
235
console.log("Rate limited - retry later");
236
break;
237
case 500:
238
case 502:
239
case 503:
240
case 504:
241
console.log("Server error - retry or show maintenance page");
242
break;
243
default:
244
console.log("HTTP error:", error.response.status);
245
}
246
} else if (error.request) {
247
console.log("No response received:", error.message);
248
} else {
249
console.log("Request setup error:", error.message);
250
}
251
} else {
252
console.log("Unknown error:", error);
253
}
254
}
255
```
256
257
### Error Response Structure
258
259
Structure of error responses when server returns an error.
260
261
```javascript { .api }
262
interface AxiosResponse<T = any, D = any> {
263
/** Response data (error details from server) */
264
data: T;
265
/** HTTP status code */
266
status: number;
267
/** HTTP status message */
268
statusText: string;
269
/** Response headers */
270
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
271
/** Request configuration */
272
config: InternalAxiosRequestConfig<D>;
273
/** Native request object */
274
request?: any;
275
}
276
```
277
278
**Usage Examples:**
279
280
```javascript
281
try {
282
await axios.post("/api/users", userData);
283
} catch (error) {
284
if (axios.isAxiosError(error) && error.response) {
285
// Server responded with error status
286
const { status, data, headers } = error.response;
287
288
console.log("Status:", status);
289
console.log("Error data:", data);
290
291
// Handle API error responses
292
if (data.errors) {
293
// Validation errors
294
data.errors.forEach(err => {
295
console.log(`${err.field}: ${err.message}`);
296
});
297
} else if (data.message) {
298
// Simple error message
299
console.log("Error:", data.message);
300
}
301
302
// Check error-specific headers
303
const retryAfter = headers["retry-after"];
304
if (status === 429 && retryAfter) {
305
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
306
}
307
}
308
}
309
```
310
311
### Global Error Handling Patterns
312
313
Common patterns for handling errors application-wide.
314
315
**Usage Examples:**
316
317
```javascript
318
// Global error interceptor
319
axios.interceptors.response.use(
320
(response) => response,
321
(error) => {
322
if (axios.isAxiosError(error)) {
323
// Log all axios errors
324
console.error("Axios Error:", {
325
url: error.config?.url,
326
method: error.config?.method,
327
status: error.response?.status,
328
message: error.message,
329
data: error.response?.data
330
});
331
332
// Handle specific error cases
333
if (error.response?.status === 401) {
334
// Redirect to login
335
localStorage.removeItem("authToken");
336
window.location.href = "/login";
337
return Promise.reject(error);
338
}
339
340
if (error.response?.status >= 500) {
341
// Show generic server error message
342
showNotification("Server error occurred. Please try again later.", "error");
343
}
344
}
345
346
return Promise.reject(error);
347
}
348
);
349
350
// Error boundary for React applications
351
class ErrorBoundary extends React.Component {
352
constructor(props) {
353
super(props);
354
this.state = { hasError: false, error: null };
355
}
356
357
static getDerivedStateFromError(error) {
358
return { hasError: true, error };
359
}
360
361
componentDidCatch(error, errorInfo) {
362
if (axios.isAxiosError(error)) {
363
// Send axios errors to monitoring service
364
sendToMonitoring({
365
type: "axios_error",
366
url: error.config?.url,
367
status: error.response?.status,
368
message: error.message,
369
stack: error.stack
370
});
371
}
372
}
373
374
render() {
375
if (this.state.hasError) {
376
return <ErrorFallback error={this.state.error} />;
377
}
378
379
return this.props.children;
380
}
381
}
382
383
// Retry with exponential backoff
384
async function retryRequest(requestFn, maxRetries = 3) {
385
for (let attempt = 1; attempt <= maxRetries; attempt++) {
386
try {
387
return await requestFn();
388
} catch (error) {
389
if (axios.isAxiosError(error)) {
390
const shouldRetry = error.response?.status >= 500 ||
391
error.code === "ECONNABORTED" ||
392
error.code === "ERR_NETWORK";
393
394
if (shouldRetry && attempt < maxRetries) {
395
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
396
console.log(`Request failed, retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`);
397
await new Promise(resolve => setTimeout(resolve, delay));
398
continue;
399
}
400
}
401
402
throw error; // Re-throw if not retryable or max retries reached
403
}
404
}
405
}
406
407
// Usage
408
try {
409
const response = await retryRequest(() =>
410
axios.get("https://unreliable-api.example.com/data")
411
);
412
console.log(response.data);
413
} catch (error) {
414
console.log("Request failed after retries:", error.message);
415
}
416
```
417
418
### Custom Error Classes
419
420
Extend AxiosError for application-specific error handling.
421
422
**Usage Examples:**
423
424
```javascript
425
// Custom error for API validation errors
426
class ValidationError extends axios.AxiosError {
427
constructor(errors, config, request, response) {
428
super("Validation failed", "VALIDATION_ERROR", config, request, response);
429
this.name = "ValidationError";
430
this.validationErrors = errors;
431
}
432
433
getFieldErrors() {
434
return this.validationErrors || [];
435
}
436
}
437
438
// Custom error for business logic errors
439
class BusinessLogicError extends axios.AxiosError {
440
constructor(businessCode, message, config, request, response) {
441
super(message, "BUSINESS_ERROR", config, request, response);
442
this.name = "BusinessLogicError";
443
this.businessCode = businessCode;
444
}
445
}
446
447
// Error factory
448
function createAppError(axiosError) {
449
if (axiosError.response?.status === 422) {
450
return new ValidationError(
451
axiosError.response.data.errors,
452
axiosError.config,
453
axiosError.request,
454
axiosError.response
455
);
456
}
457
458
if (axiosError.response?.data?.businessCode) {
459
return new BusinessLogicError(
460
axiosError.response.data.businessCode,
461
axiosError.response.data.message,
462
axiosError.config,
463
axiosError.request,
464
axiosError.response
465
);
466
}
467
468
return axiosError; // Return original error
469
}
470
471
// Usage in interceptor
472
axios.interceptors.response.use(
473
(response) => response,
474
(error) => {
475
if (axios.isAxiosError(error)) {
476
throw createAppError(error);
477
}
478
throw error;
479
}
480
);
481
```