0
# Error Handling
1
2
Comprehensive error hierarchy covering all HTTP operation failure modes. Undici provides specific error types for different failure scenarios to enable precise error handling and debugging.
3
4
## Capabilities
5
6
### Base Error Class
7
8
```typescript { .api }
9
/**
10
* Base class for all Undici errors
11
*/
12
class UndiciError extends Error {
13
name: string;
14
code: string;
15
16
constructor(message?: string);
17
}
18
```
19
20
### Connection Errors
21
22
Errors related to establishing and maintaining connections.
23
24
```typescript { .api }
25
/**
26
* Thrown when connection establishment times out
27
*/
28
class ConnectTimeoutError extends UndiciError {
29
name: "ConnectTimeoutError";
30
code: "UND_ERR_CONNECT_TIMEOUT";
31
}
32
33
/**
34
* Thrown when socket-level errors occur
35
*/
36
class SocketError extends UndiciError {
37
name: "SocketError";
38
code: "UND_ERR_SOCKET";
39
socket: {
40
localAddress?: string;
41
localPort?: number;
42
remoteAddress?: string;
43
remotePort?: number;
44
};
45
}
46
47
/**
48
* Thrown when client is destroyed unexpectedly
49
*/
50
class ClientDestroyedError extends UndiciError {
51
name: "ClientDestroyedError";
52
code: "UND_ERR_DESTROYED";
53
}
54
55
/**
56
* Thrown when client is closed unexpectedly
57
*/
58
class ClientClosedError extends UndiciError {
59
name: "ClientClosedError";
60
code: "UND_ERR_CLOSED";
61
}
62
63
/**
64
* Thrown when secure proxy connection fails
65
*/
66
class SecureProxyConnectionError extends UndiciError {
67
name: "SecureProxyConnectionError";
68
code: "UND_ERR_PRX_TLS";
69
cause?: Error;
70
}
71
```
72
73
**Usage Examples:**
74
75
```typescript
76
import {
77
Client,
78
ConnectTimeoutError,
79
SocketError,
80
ClientDestroyedError
81
} from "undici-types";
82
83
const client = new Client("https://unreliable.example.com", {
84
headersTimeout: 5000
85
});
86
87
try {
88
const response = await client.request({
89
path: "/api/data",
90
method: "GET"
91
});
92
} catch (error) {
93
if (error instanceof ConnectTimeoutError) {
94
console.error("Connection timed out:", error.message);
95
// Implement retry logic or fallback
96
} else if (error instanceof SocketError) {
97
console.error("Socket error:", error.message);
98
console.error("Connection details:", error.socket);
99
// Log connection details for debugging
100
} else if (error instanceof ClientDestroyedError) {
101
console.error("Client was destroyed:", error.message);
102
// Create new client instance
103
}
104
}
105
```
106
107
### Timeout Errors
108
109
Errors related to various timeout scenarios during HTTP operations.
110
111
```typescript { .api }
112
/**
113
* Thrown when response headers are not received within timeout
114
*/
115
class HeadersTimeoutError extends UndiciError {
116
name: "HeadersTimeoutError";
117
code: "UND_ERR_HEADERS_TIMEOUT";
118
}
119
120
/**
121
* Thrown when response body is not received within timeout
122
*/
123
class BodyTimeoutError extends UndiciError {
124
name: "BodyTimeoutError";
125
code: "UND_ERR_BODY_TIMEOUT";
126
}
127
128
/**
129
* Thrown when headers exceed maximum size limit
130
*/
131
class HeadersOverflowError extends UndiciError {
132
name: "HeadersOverflowError";
133
code: "UND_ERR_HEADERS_OVERFLOW";
134
}
135
136
/**
137
* Thrown when response size exceeds maximum limit
138
*/
139
class ResponseExceededMaxSizeError extends UndiciError {
140
name: "ResponseExceededMaxSizeError";
141
code: "UND_ERR_RES_EXCEEDED_MAX_SIZE";
142
maxSize: number;
143
}
144
```
145
146
**Usage Examples:**
147
148
```typescript
149
import {
150
request,
151
HeadersTimeoutError,
152
BodyTimeoutError,
153
ResponseExceededMaxSizeError
154
} from "undici-types";
155
156
try {
157
const response = await request("https://slow-api.example.com/large-data", {
158
headersTimeout: 10000,
159
bodyTimeout: 30000
160
});
161
162
const data = await response.body.text();
163
} catch (error) {
164
if (error instanceof HeadersTimeoutError) {
165
console.error("Headers not received in time");
166
// Retry with longer timeout or different endpoint
167
} else if (error instanceof BodyTimeoutError) {
168
console.error("Body not received in time");
169
// Switch to streaming approach or increase timeout
170
} else if (error instanceof ResponseExceededMaxSizeError) {
171
console.error(`Response too large: ${error.maxSize} bytes`);
172
// Use streaming or pagination instead
173
}
174
}
175
```
176
177
### Request/Response Errors
178
179
Errors related to request processing and response handling.
180
181
```typescript { .api }
182
/**
183
* Thrown when request is aborted
184
*/
185
class RequestAbortedError extends UndiciError {
186
name: "RequestAbortedError";
187
code: "UND_ERR_ABORTED";
188
}
189
190
/**
191
* Thrown for general response errors
192
*/
193
class ResponseError extends UndiciError {
194
constructor(
195
message: string,
196
code: number,
197
options: {
198
headers?: IncomingHttpHeaders | string[] | null;
199
body?: null | Record<string, any> | string;
200
}
201
);
202
203
name: "ResponseError";
204
code: "UND_ERR_RESPONSE";
205
statusCode: number;
206
body: null | Record<string, any> | string;
207
headers: IncomingHttpHeaders | string[] | null;
208
}
209
210
/**
211
* Thrown for specific HTTP status code errors
212
*/
213
class ResponseStatusCodeError extends UndiciError {
214
constructor(
215
message?: string,
216
statusCode?: number,
217
headers?: IncomingHttpHeaders | string[] | null,
218
body?: null | Record<string, any> | string
219
);
220
221
name: "ResponseStatusCodeError";
222
code: "UND_ERR_RESPONSE_STATUS_CODE";
223
body: null | Record<string, any> | string;
224
status: number;
225
statusCode: number;
226
headers: IncomingHttpHeaders | string[] | null;
227
}
228
229
/**
230
* Thrown when request retry fails after maximum attempts
231
*/
232
class RequestRetryError extends UndiciError {
233
constructor(
234
message: string,
235
statusCode: number,
236
headers?: IncomingHttpHeaders | string[] | null,
237
body?: null | Record<string, any> | string
238
);
239
240
name: "RequestRetryError";
241
code: "UND_ERR_REQ_RETRY";
242
statusCode: number;
243
data: {
244
count: number;
245
};
246
headers: Record<string, string | string[]>;
247
}
248
249
/**
250
* Thrown when request content length doesn't match actual body size
251
*/
252
class RequestContentLengthMismatchError extends UndiciError {
253
name: "RequestContentLengthMismatchError";
254
code: "UND_ERR_REQ_CONTENT_LENGTH_MISMATCH";
255
}
256
257
/**
258
* Thrown when response content length doesn't match actual body size
259
*/
260
class ResponseContentLengthMismatchError extends UndiciError {
261
name: "ResponseContentLengthMismatchError";
262
code: "UND_ERR_RES_CONTENT_LENGTH_MISMATCH";
263
}
264
```
265
266
**Usage Examples:**
267
268
```typescript
269
import {
270
request,
271
RequestAbortedError,
272
ResponseStatusCodeError,
273
ResponseContentLengthMismatchError
274
} from "undici-types";
275
276
// Request with AbortController
277
const controller = new AbortController();
278
setTimeout(() => controller.abort(), 5000);
279
280
try {
281
const response = await request("https://api.example.com/slow-endpoint", {
282
signal: controller.signal,
283
throwOnError: true // Enable automatic status code error throwing
284
});
285
286
const data = await response.body.json();
287
} catch (error) {
288
if (error instanceof RequestAbortedError) {
289
console.error("Request was aborted");
290
// Handle cancellation
291
} else if (error instanceof ResponseStatusCodeError) {
292
console.error(`HTTP ${error.status}: ${error.statusText}`);
293
console.error("Response body:", error.body);
294
console.error("Response headers:", error.headers);
295
296
// Handle specific status codes
297
if (error.status === 401) {
298
// Handle authentication error
299
} else if (error.status === 429) {
300
// Handle rate limiting
301
const retryAfter = error.headers['retry-after'];
302
console.log(`Retry after: ${retryAfter} seconds`);
303
}
304
} else if (error instanceof ResponseContentLengthMismatchError) {
305
console.error("Response content length mismatch - possible truncated response");
306
// Retry request or handle partial data
307
}
308
}
309
```
310
311
### Validation Errors
312
313
Errors related to input validation and argument checking.
314
315
```typescript { .api }
316
/**
317
* Thrown when invalid arguments are provided
318
*/
319
class InvalidArgumentError extends UndiciError {
320
name: "InvalidArgumentError";
321
code: "UND_ERR_INVALID_ARG";
322
}
323
324
/**
325
* Thrown when invalid return values are encountered
326
*/
327
class InvalidReturnValueError extends UndiciError {
328
name: "InvalidReturnValueError";
329
code: "UND_ERR_INVALID_RETURN_VALUE";
330
}
331
332
/**
333
* Thrown when functionality is not supported
334
*/
335
class NotSupportedError extends UndiciError {
336
name: "NotSupportedError";
337
code: "UND_ERR_NOT_SUPPORTED";
338
}
339
```
340
341
**Usage Examples:**
342
343
```typescript
344
import {
345
Client,
346
InvalidArgumentError,
347
NotSupportedError
348
} from "undici-types";
349
350
try {
351
// This might throw InvalidArgumentError for invalid URL
352
const client = new Client("invalid-url");
353
354
// This might throw InvalidArgumentError for invalid method
355
await client.request({
356
path: "/api/data",
357
method: "INVALID_METHOD" as any
358
});
359
} catch (error) {
360
if (error instanceof InvalidArgumentError) {
361
console.error("Invalid argument provided:", error.message);
362
// Validate inputs before making requests
363
} else if (error instanceof NotSupportedError) {
364
console.error("Feature not supported:", error.message);
365
// Use alternative approach
366
}
367
}
368
```
369
370
### Pool and Agent Errors
371
372
Errors specific to connection pools and agents.
373
374
```typescript { .api }
375
/**
376
* Thrown when balanced pool has no available upstreams
377
*/
378
class BalancedPoolMissingUpstreamError extends UndiciError {
379
name: "BalancedPoolMissingUpstreamError";
380
code: "UND_ERR_BPL_MISSING_UPSTREAM";
381
}
382
383
/**
384
* Thrown on HTTP parsing errors
385
*/
386
class HTTPParserError extends UndiciError {
387
name: "HTTPParserError";
388
code: "UND_ERR_PARSER";
389
bytesParsed: number;
390
}
391
392
/**
393
* Thrown on informational status code errors (1xx)
394
*/
395
class InformationalError extends UndiciError {
396
name: "InformationalError";
397
code: "UND_ERR_INFO";
398
status: number;
399
statusText: string;
400
headers: Record<string, string | string[]>;
401
}
402
```
403
404
**Usage Examples:**
405
406
```typescript
407
import {
408
BalancedPool,
409
BalancedPoolMissingUpstreamError,
410
HTTPParserError
411
} from "undici-types";
412
413
// Balanced pool example
414
const pool = new BalancedPool([]);
415
416
try {
417
await pool.request({
418
path: "/api/data",
419
method: "GET"
420
});
421
} catch (error) {
422
if (error instanceof BalancedPoolMissingUpstreamError) {
423
console.error("No upstreams available in balanced pool");
424
// Add upstreams or use fallback
425
pool.addUpstream("https://backup.example.com");
426
} else if (error instanceof HTTPParserError) {
427
console.error("HTTP parsing error:", error.message);
428
console.error("Bytes parsed:", error.bytesParsed);
429
// Log for debugging malformed responses
430
}
431
}
432
```
433
434
### Retry Errors
435
436
Errors related to retry operations.
437
438
```typescript { .api }
439
/**
440
* Thrown when request retry fails after all attempts
441
*/
442
class RequestRetryError extends UndiciError {
443
name: "RequestRetryError";
444
code: "UND_ERR_REQ_RETRY";
445
statusCode: number;
446
data: {
447
count: number;
448
maxCount: number;
449
};
450
cause?: Error;
451
}
452
```
453
454
**Usage Examples:**
455
456
```typescript
457
import {
458
RetryAgent,
459
Agent,
460
RequestRetryError
461
} from "undici-types";
462
463
const retryAgent = new RetryAgent(new Agent(), {
464
retry: 3,
465
maxTimeout: 30000
466
});
467
468
try {
469
const response = await retryAgent.request({
470
origin: "https://unreliable-api.example.com",
471
path: "/api/data",
472
method: "GET"
473
});
474
} catch (error) {
475
if (error instanceof RequestRetryError) {
476
console.error(`Request failed after ${error.data.count} attempts`);
477
console.error(`Max attempts: ${error.data.maxCount}`);
478
console.error(`Final status: ${error.statusCode}`);
479
console.error(`Underlying cause:`, error.cause);
480
481
// Handle final failure
482
// Maybe try alternative endpoint or return cached data
483
}
484
}
485
```
486
487
## Error Namespace
488
489
All errors are also available through the errors namespace:
490
491
```typescript { .api }
492
namespace errors {
493
const UndiciError: typeof UndiciError;
494
const ConnectTimeoutError: typeof ConnectTimeoutError;
495
const HeadersTimeoutError: typeof HeadersTimeoutError;
496
const HeadersOverflowError: typeof HeadersOverflowError;
497
const BodyTimeoutError: typeof BodyTimeoutError;
498
const ResponseError: typeof ResponseError;
499
const ResponseStatusCodeError: typeof ResponseStatusCodeError;
500
const InvalidArgumentError: typeof InvalidArgumentError;
501
const InvalidReturnValueError: typeof InvalidReturnValueError;
502
const RequestAbortedError: typeof RequestAbortedError;
503
const InformationalError: typeof InformationalError;
504
const RequestContentLengthMismatchError: typeof RequestContentLengthMismatchError;
505
const ResponseContentLengthMismatchError: typeof ResponseContentLengthMismatchError;
506
const ClientDestroyedError: typeof ClientDestroyedError;
507
const ClientClosedError: typeof ClientClosedError;
508
const SocketError: typeof SocketError;
509
const NotSupportedError: typeof NotSupportedError;
510
const BalancedPoolMissingUpstreamError: typeof BalancedPoolMissingUpstreamError;
511
const HTTPParserError: typeof HTTPParserError;
512
const ResponseExceededMaxSizeError: typeof ResponseExceededMaxSizeError;
513
const RequestRetryError: typeof RequestRetryError;
514
const SecureProxyConnectionError: typeof SecureProxyConnectionError;
515
}
516
```
517
518
**Usage Examples:**
519
520
```typescript
521
import { errors } from "undici-types";
522
523
// Use errors namespace
524
try {
525
// Some HTTP operation
526
} catch (error) {
527
if (error instanceof errors.ConnectTimeoutError) {
528
// Handle connection timeout
529
} else if (error instanceof errors.ResponseStatusCodeError) {
530
// Handle HTTP status errors
531
}
532
}
533
534
// Error type checking utility
535
function isUndiciError(error: unknown): error is UndiciError {
536
return error instanceof errors.UndiciError;
537
}
538
539
function handleHttpError(error: unknown) {
540
if (!isUndiciError(error)) {
541
throw error; // Re-throw non-Undici errors
542
}
543
544
switch (error.code) {
545
case "UND_ERR_CONNECT_TIMEOUT":
546
return "Connection timed out - check network connectivity";
547
case "UND_ERR_RESPONSE_STATUS_CODE":
548
return `HTTP error: ${(error as errors.ResponseStatusCodeError).status}`;
549
case "UND_ERR_ABORTED":
550
return "Request was cancelled";
551
default:
552
return `Undici error: ${error.message}`;
553
}
554
}
555
```