or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdconnection-management.mdcookies.mdcore-http.mderrors.mdglobal-config.mdheaders-body.mdindex.mdinterceptors.mdmock-testing.mdweb-standards.md

errors.mddocs/

0

# Error Handling

1

2

Comprehensive error classes for different types of HTTP client failures with detailed error information and proper error handling patterns.

3

4

## Capabilities

5

6

### Error Classes

7

8

Undici provides specific error types for different failure scenarios to enable precise error handling.

9

10

```javascript { .api }

11

/**

12

* All undici error types

13

*/

14

const errors: {

15

UndiciError: typeof UndiciError;

16

ConnectTimeoutError: typeof ConnectTimeoutError;

17

HeadersTimeoutError: typeof HeadersTimeoutError;

18

BodyTimeoutError: typeof BodyTimeoutError;

19

ResponseError: typeof ResponseError;

20

ResponseStatusCodeError: typeof ResponseStatusCodeError;

21

RequestRetryError: typeof RequestRetryError;

22

ClientDestroyedError: typeof ClientDestroyedError;

23

ClientClosedError: typeof ClientClosedError;

24

SocketError: typeof SocketError;

25

NotSupportedError: typeof NotSupportedError;

26

InvalidArgumentError: typeof InvalidArgumentError;

27

InvalidReturnValueError: typeof InvalidReturnValueError;

28

RequestAbortedError: typeof RequestAbortedError;

29

InformationalError: typeof InformationalError;

30

RequestContentLengthMismatchError: typeof RequestContentLengthMismatchError;

31

ResponseContentLengthMismatchError: typeof ResponseContentLengthMismatchError;

32

HeadersOverflowError: typeof HeadersOverflowError;

33

HTTPParserError: typeof HTTPParserError;

34

};

35

```

36

37

### Base Error Class

38

39

```javascript { .api }

40

/**

41

* Base class for all undici errors

42

*/

43

class UndiciError extends Error {

44

name: string;

45

code: string;

46

message: string;

47

}

48

```

49

50

### Network Timeout Errors

51

52

Errors related to network timeouts during different phases of the request.

53

54

```javascript { .api }

55

/**

56

* Connection establishment timeout

57

*/

58

class ConnectTimeoutError extends UndiciError {

59

name: 'ConnectTimeoutError';

60

code: 'UND_ERR_CONNECT_TIMEOUT';

61

message: string;

62

}

63

64

/**

65

* Headers reception timeout

66

*/

67

class HeadersTimeoutError extends UndiciError {

68

name: 'HeadersTimeoutError';

69

code: 'UND_ERR_HEADERS_TIMEOUT';

70

message: string;

71

}

72

73

/**

74

* Body reception timeout

75

*/

76

class BodyTimeoutError extends UndiciError {

77

name: 'BodyTimeoutError';

78

code: 'UND_ERR_BODY_TIMEOUT';

79

message: string;

80

}

81

```

82

83

**Usage Examples:**

84

85

```javascript

86

import { request, errors } from 'undici';

87

88

try {

89

const response = await request('https://slow-server.example.com/data', {

90

headersTimeout: 5000, // 5 second headers timeout

91

bodyTimeout: 10000 // 10 second body timeout

92

});

93

} catch (error) {

94

if (error instanceof errors.ConnectTimeoutError) {

95

console.log('Failed to establish connection within timeout');

96

} else if (error instanceof errors.HeadersTimeoutError) {

97

console.log('Headers not received within timeout');

98

} else if (error instanceof errors.BodyTimeoutError) {

99

console.log('Response body not received within timeout');

100

}

101

}

102

```

103

104

### HTTP Response Errors

105

106

Errors related to HTTP response processing and status codes.

107

108

```javascript { .api }

109

/**

110

* General HTTP response error

111

*/

112

class ResponseError extends UndiciError {

113

name: 'ResponseError';

114

code: 'UND_ERR_RESPONSE';

115

statusCode: number;

116

headers: Record<string, string | string[]>;

117

body: any;

118

}

119

120

/**

121

* HTTP status code error

122

*/

123

class ResponseStatusCodeError extends UndiciError {

124

name: 'ResponseStatusCodeError';

125

code: 'UND_ERR_RESPONSE_STATUS_CODE';

126

statusCode: number;

127

headers: Record<string, string | string[]>;

128

body: any;

129

}

130

131

/**

132

* Request retry error after exhausting retries

133

*/

134

class RequestRetryError extends UndiciError {

135

name: 'RequestRetryError';

136

code: 'UND_ERR_REQ_RETRY';

137

statusCode?: number;

138

data: {

139

count: number;

140

error: Error;

141

};

142

}

143

```

144

145

**Usage Examples:**

146

147

```javascript

148

import { request, errors } from 'undici';

149

150

try {

151

const response = await request('https://api.example.com/protected', {

152

method: 'GET',

153

throwOnError: true

154

});

155

} catch (error) {

156

if (error instanceof errors.ResponseStatusCodeError) {

157

console.log(`HTTP ${error.statusCode}: ${error.message}`);

158

console.log('Response headers:', error.headers);

159

console.log('Response body:', error.body);

160

161

// Handle specific status codes

162

if (error.statusCode === 401) {

163

console.log('Authentication required');

164

} else if (error.statusCode === 403) {

165

console.log('Access forbidden');

166

} else if (error.statusCode >= 500) {

167

console.log('Server error occurred');

168

}

169

} else if (error instanceof errors.RequestRetryError) {

170

console.log(`Request failed after ${error.data.count} retries`);

171

console.log('Original error:', error.data.error.message);

172

}

173

}

174

```

175

176

### Client State Errors

177

178

Errors related to client lifecycle and state management.

179

180

```javascript { .api }

181

/**

182

* Using destroyed client

183

*/

184

class ClientDestroyedError extends UndiciError {

185

name: 'ClientDestroyedError';

186

code: 'UND_ERR_DESTROYED';

187

message: 'The client is destroyed';

188

}

189

190

/**

191

* Using closed client

192

*/

193

class ClientClosedError extends UndiciError {

194

name: 'ClientClosedError';

195

code: 'UND_ERR_CLOSED';

196

message: 'The client is closed';

197

}

198

199

/**

200

* Request aborted by user

201

*/

202

class RequestAbortedError extends UndiciError {

203

name: 'RequestAbortedError';

204

code: 'UND_ERR_ABORTED';

205

message: 'Request aborted';

206

}

207

```

208

209

**Usage Examples:**

210

211

```javascript

212

import { Client, errors } from 'undici';

213

214

const client = new Client('https://api.example.com');

215

216

// Destroy client

217

await client.destroy();

218

219

try {

220

// This will throw ClientDestroyedError

221

await client.request({ path: '/data' });

222

} catch (error) {

223

if (error instanceof errors.ClientDestroyedError) {

224

console.log('Cannot use destroyed client');

225

}

226

}

227

228

// Abort request example

229

const controller = new AbortController();

230

231

// Abort after 2 seconds

232

setTimeout(() => controller.abort(), 2000);

233

234

try {

235

const response = await client.request({

236

path: '/slow-endpoint',

237

signal: controller.signal

238

});

239

} catch (error) {

240

if (error instanceof errors.RequestAbortedError) {

241

console.log('Request was aborted');

242

}

243

}

244

```

245

246

### Protocol and Parsing Errors

247

248

Errors related to HTTP protocol violations and parsing failures.

249

250

```javascript { .api }

251

/**

252

* Low-level socket errors

253

*/

254

class SocketError extends UndiciError {

255

name: 'SocketError';

256

code: 'UND_ERR_SOCKET';

257

socket: {

258

localAddress: string;

259

localPort: number;

260

remoteAddress: string;

261

remotePort: number;

262

};

263

}

264

265

/**

266

* Headers size exceeds limits

267

*/

268

class HeadersOverflowError extends UndiciError {

269

name: 'HeadersOverflowError';

270

code: 'UND_ERR_HEADERS_OVERFLOW';

271

message: 'Headers overflow';

272

}

273

274

/**

275

* Request body length mismatch

276

*/

277

class RequestContentLengthMismatchError extends UndiciError {

278

name: 'RequestContentLengthMismatchError';

279

code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH';

280

message: 'Request body length does not match content-length header';

281

}

282

283

/**

284

* Response body length mismatch

285

*/

286

class ResponseContentLengthMismatchError extends UndiciError {

287

name: 'ResponseContentLengthMismatchError';

288

code: 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH';

289

message: 'Response body length does not match content-length header';

290

}

291

292

/**

293

* HTTP parsing errors

294

*/

295

class HTTPParserError extends Error {

296

name: 'HTTPParserError';

297

code: string;

298

bytesParsed: number;

299

}

300

```

301

302

**Usage Examples:**

303

304

```javascript

305

import { request, errors } from 'undici';

306

307

try {

308

const response = await request('https://malformed-server.example.com/data');

309

} catch (error) {

310

if (error instanceof errors.HTTPParserError) {

311

console.log('HTTP parsing failed:', error.message);

312

console.log('Bytes parsed:', error.bytesParsed);

313

} else if (error instanceof errors.HeadersOverflowError) {

314

console.log('Response headers too large');

315

} else if (error instanceof errors.ResponseContentLengthMismatchError) {

316

console.log('Response body length mismatch');

317

} else if (error instanceof errors.SocketError) {

318

console.log('Socket error:', error.message);

319

console.log('Socket info:', error.socket);

320

}

321

}

322

```

323

324

### Validation Errors

325

326

Errors related to invalid arguments and return values.

327

328

```javascript { .api }

329

/**

330

* Invalid function arguments

331

*/

332

class InvalidArgumentError extends UndiciError {

333

name: 'InvalidArgumentError';

334

code: 'UND_ERR_INVALID_ARG';

335

message: string;

336

}

337

338

/**

339

* Invalid return values

340

*/

341

class InvalidReturnValueError extends UndiciError {

342

name: 'InvalidReturnValueError';

343

code: 'UND_ERR_INVALID_RETURN_VALUE';

344

message: string;

345

}

346

347

/**

348

* Unsupported functionality

349

*/

350

class NotSupportedError extends UndiciError {

351

name: 'NotSupportedError';

352

code: 'UND_ERR_NOT_SUPPORTED';

353

message: string;

354

}

355

```

356

357

**Usage Examples:**

358

359

```javascript

360

import { request, errors } from 'undici';

361

362

try {

363

// Invalid URL will throw InvalidArgumentError

364

await request(null);

365

} catch (error) {

366

if (error instanceof errors.InvalidArgumentError) {

367

console.log('Invalid argument provided:', error.message);

368

}

369

}

370

371

try {

372

// Unsupported feature

373

await request('https://api.example.com', {

374

method: 'INVALID_METHOD'

375

});

376

} catch (error) {

377

if (error instanceof errors.NotSupportedError) {

378

console.log('Feature not supported:', error.message);

379

}

380

}

381

```

382

383

## Error Handling Patterns

384

385

### Comprehensive Error Handling

386

387

```javascript

388

import { request, errors } from 'undici';

389

390

async function safeRequest(url, options = {}) {

391

try {

392

return await request(url, {

393

...options,

394

headersTimeout: 10000,

395

bodyTimeout: 30000,

396

throwOnError: true

397

});

398

} catch (error) {

399

// Network and timeout errors

400

if (error instanceof errors.ConnectTimeoutError) {

401

throw new Error('Connection timeout - server may be down');

402

}

403

404

if (error instanceof errors.HeadersTimeoutError) {

405

throw new Error('Headers timeout - server may be overloaded');

406

}

407

408

if (error instanceof errors.BodyTimeoutError) {

409

throw new Error('Body timeout - response too large or slow');

410

}

411

412

// HTTP response errors

413

if (error instanceof errors.ResponseStatusCodeError) {

414

switch (error.statusCode) {

415

case 400:

416

throw new Error('Bad request - check your request data');

417

case 401:

418

throw new Error('Authentication required');

419

case 403:

420

throw new Error('Access forbidden');

421

case 404:

422

throw new Error('Resource not found');

423

case 429:

424

throw new Error('Rate limit exceeded');

425

case 500:

426

throw new Error('Internal server error');

427

case 502:

428

case 503:

429

case 504:

430

throw new Error('Server temporarily unavailable');

431

default:

432

throw new Error(`HTTP ${error.statusCode}: ${error.message}`);

433

}

434

}

435

436

// Client state errors

437

if (error instanceof errors.ClientDestroyedError) {

438

throw new Error('HTTP client was destroyed');

439

}

440

441

if (error instanceof errors.RequestAbortedError) {

442

throw new Error('Request was cancelled');

443

}

444

445

// Protocol errors

446

if (error instanceof errors.HTTPParserError) {

447

throw new Error('Invalid HTTP response from server');

448

}

449

450

// Validation errors

451

if (error instanceof errors.InvalidArgumentError) {

452

throw new Error('Invalid request parameters');

453

}

454

455

// Unknown error

456

throw new Error(`Unexpected error: ${error.message}`);

457

}

458

}

459

```

460

461

### Retry with Error Classification

462

463

```javascript

464

import { request, errors } from 'undici';

465

466

async function requestWithRetry(url, options = {}, maxRetries = 3) {

467

let attempt = 0;

468

469

while (attempt <= maxRetries) {

470

try {

471

return await request(url, options);

472

} catch (error) {

473

attempt++;

474

475

// Don't retry client errors (4xx) or validation errors

476

if (

477

error instanceof errors.ResponseStatusCodeError &&

478

error.statusCode >= 400 && error.statusCode < 500

479

) {

480

throw error;

481

}

482

483

if (

484

error instanceof errors.InvalidArgumentError ||

485

error instanceof errors.NotSupportedError ||

486

error instanceof errors.ClientDestroyedError

487

) {

488

throw error;

489

}

490

491

// Retry on network errors, timeouts, and server errors

492

const shouldRetry =

493

error instanceof errors.ConnectTimeoutError ||

494

error instanceof errors.HeadersTimeoutError ||

495

error instanceof errors.BodyTimeoutError ||

496

error instanceof errors.SocketError ||

497

(error instanceof errors.ResponseStatusCodeError &&

498

error.statusCode >= 500);

499

500

if (!shouldRetry || attempt > maxRetries) {

501

throw error;

502

}

503

504

// Exponential backoff

505

const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);

506

await new Promise(resolve => setTimeout(resolve, delay));

507

}

508

}

509

}

510

```

511

512

### Error Logging and Monitoring

513

514

```javascript

515

import { request, errors } from 'undici';

516

517

function logError(error, context = {}) {

518

const errorInfo = {

519

timestamp: new Date().toISOString(),

520

name: error.name,

521

code: error.code,

522

message: error.message,

523

...context

524

};

525

526

// Add specific error details

527

if (error instanceof errors.ResponseStatusCodeError) {

528

errorInfo.statusCode = error.statusCode;

529

errorInfo.headers = error.headers;

530

}

531

532

if (error instanceof errors.RequestRetryError) {

533

errorInfo.retryCount = error.data.count;

534

errorInfo.originalError = error.data.error.message;

535

}

536

537

if (error instanceof errors.SocketError && error.socket) {

538

errorInfo.socket = error.socket;

539

}

540

541

console.error('HTTP Request Error:', JSON.stringify(errorInfo, null, 2));

542

543

// Send to monitoring service

544

// monitoringService.logError(errorInfo);

545

}

546

547

async function monitoredRequest(url, options = {}) {

548

try {

549

return await request(url, options);

550

} catch (error) {

551

logError(error, { url, method: options.method || 'GET' });

552

throw error;

553

}

554

}

555

```