CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-undici-types

A stand-alone types package for Undici HTTP client library

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

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.

Capabilities

Base Error Class

/**
 * Base class for all Undici errors
 */
class UndiciError extends Error {
  name: string;
  code: string;
  
  constructor(message?: string);
}

Connection Errors

Errors related to establishing and maintaining connections.

/**
 * Thrown when connection establishment times out
 */
class ConnectTimeoutError extends UndiciError {
  name: "ConnectTimeoutError";
  code: "UND_ERR_CONNECT_TIMEOUT";
}

/**
 * Thrown when socket-level errors occur
 */
class SocketError extends UndiciError {
  name: "SocketError";
  code: "UND_ERR_SOCKET";
  socket: {
    localAddress?: string;
    localPort?: number;
    remoteAddress?: string;
    remotePort?: number;
  };
}

/**
 * Thrown when client is destroyed unexpectedly
 */
class ClientDestroyedError extends UndiciError {
  name: "ClientDestroyedError";
  code: "UND_ERR_DESTROYED";
}

/**
 * Thrown when client is closed unexpectedly
 */
class ClientClosedError extends UndiciError {
  name: "ClientClosedError";  
  code: "UND_ERR_CLOSED";
}

/**
 * Thrown when secure proxy connection fails
 */
class SecureProxyConnectionError extends UndiciError {
  name: "SecureProxyConnectionError";
  code: "UND_ERR_PRX_TLS";
  cause?: Error;
}

Usage Examples:

import { 
  Client, 
  ConnectTimeoutError,
  SocketError,
  ClientDestroyedError 
} from "undici-types";

const client = new Client("https://unreliable.example.com", {
  headersTimeout: 5000
});

try {
  const response = await client.request({
    path: "/api/data",
    method: "GET"
  });
} catch (error) {
  if (error instanceof ConnectTimeoutError) {
    console.error("Connection timed out:", error.message);
    // Implement retry logic or fallback
  } else if (error instanceof SocketError) {
    console.error("Socket error:", error.message);
    console.error("Connection details:", error.socket);
    // Log connection details for debugging
  } else if (error instanceof ClientDestroyedError) {
    console.error("Client was destroyed:", error.message);
    // Create new client instance
  }
}

Timeout Errors

Errors related to various timeout scenarios during HTTP operations.

/**
 * Thrown when response headers are not received within timeout
 */
class HeadersTimeoutError extends UndiciError {
  name: "HeadersTimeoutError";
  code: "UND_ERR_HEADERS_TIMEOUT";
}

/**
 * Thrown when response body is not received within timeout
 */
class BodyTimeoutError extends UndiciError {
  name: "BodyTimeoutError";
  code: "UND_ERR_BODY_TIMEOUT";
}

/**
 * Thrown when headers exceed maximum size limit
 */
class HeadersOverflowError extends UndiciError {
  name: "HeadersOverflowError";
  code: "UND_ERR_HEADERS_OVERFLOW";
}

/**
 * Thrown when response size exceeds maximum limit
 */
class ResponseExceededMaxSizeError extends UndiciError {
  name: "ResponseExceededMaxSizeError";
  code: "UND_ERR_RES_EXCEEDED_MAX_SIZE";
  maxSize: number;
}

Usage Examples:

import { 
  request,
  HeadersTimeoutError,
  BodyTimeoutError,
  ResponseExceededMaxSizeError 
} from "undici-types";

try {
  const response = await request("https://slow-api.example.com/large-data", {
    headersTimeout: 10000,
    bodyTimeout: 30000
  });
  
  const data = await response.body.text();
} catch (error) {
  if (error instanceof HeadersTimeoutError) {
    console.error("Headers not received in time");
    // Retry with longer timeout or different endpoint
  } else if (error instanceof BodyTimeoutError) {
    console.error("Body not received in time");
    // Switch to streaming approach or increase timeout
  } else if (error instanceof ResponseExceededMaxSizeError) {
    console.error(`Response too large: ${error.maxSize} bytes`);
    // Use streaming or pagination instead
  }
}

Request/Response Errors

Errors related to request processing and response handling.

/**
 * Thrown when request is aborted
 */
class RequestAbortedError extends UndiciError {
  name: "RequestAbortedError";
  code: "UND_ERR_ABORTED";
}

/**
 * Thrown for general response errors
 */
class ResponseError extends UndiciError {
  constructor(
    message: string,
    code: number,
    options: {
      headers?: IncomingHttpHeaders | string[] | null;
      body?: null | Record<string, any> | string;
    }
  );
  
  name: "ResponseError";
  code: "UND_ERR_RESPONSE";
  statusCode: number;
  body: null | Record<string, any> | string;
  headers: IncomingHttpHeaders | string[] | null;
}

/**
 * Thrown for specific HTTP status code errors
 */
class ResponseStatusCodeError extends UndiciError {
  constructor(
    message?: string,
    statusCode?: number,
    headers?: IncomingHttpHeaders | string[] | null,
    body?: null | Record<string, any> | string
  );
  
  name: "ResponseStatusCodeError";
  code: "UND_ERR_RESPONSE_STATUS_CODE";
  body: null | Record<string, any> | string;
  status: number;
  statusCode: number;
  headers: IncomingHttpHeaders | string[] | null;
}

/**
 * Thrown when request retry fails after maximum attempts
 */
class RequestRetryError extends UndiciError {
  constructor(
    message: string,
    statusCode: number,
    headers?: IncomingHttpHeaders | string[] | null,
    body?: null | Record<string, any> | string
  );
  
  name: "RequestRetryError";
  code: "UND_ERR_REQ_RETRY";
  statusCode: number;
  data: {
    count: number;
  };
  headers: Record<string, string | string[]>;
}

/**
 * Thrown when request content length doesn't match actual body size
 */
class RequestContentLengthMismatchError extends UndiciError {
  name: "RequestContentLengthMismatchError";
  code: "UND_ERR_REQ_CONTENT_LENGTH_MISMATCH";
}

/**
 * Thrown when response content length doesn't match actual body size
 */
class ResponseContentLengthMismatchError extends UndiciError {
  name: "ResponseContentLengthMismatchError";
  code: "UND_ERR_RES_CONTENT_LENGTH_MISMATCH";
}

Usage Examples:

import { 
  request,
  RequestAbortedError,
  ResponseStatusCodeError,
  ResponseContentLengthMismatchError 
} from "undici-types";

// Request with AbortController
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

try {
  const response = await request("https://api.example.com/slow-endpoint", {
    signal: controller.signal,
    throwOnError: true // Enable automatic status code error throwing
  });
  
  const data = await response.body.json();
} catch (error) {
  if (error instanceof RequestAbortedError) {
    console.error("Request was aborted");
    // Handle cancellation
  } else if (error instanceof ResponseStatusCodeError) {
    console.error(`HTTP ${error.status}: ${error.statusText}`);
    console.error("Response body:", error.body);
    console.error("Response headers:", error.headers);
    
    // Handle specific status codes
    if (error.status === 401) {
      // Handle authentication error
    } else if (error.status === 429) {
      // Handle rate limiting
      const retryAfter = error.headers['retry-after'];
      console.log(`Retry after: ${retryAfter} seconds`);
    }
  } else if (error instanceof ResponseContentLengthMismatchError) {
    console.error("Response content length mismatch - possible truncated response");
    // Retry request or handle partial data
  }
}

Validation Errors

Errors related to input validation and argument checking.

/**
 * Thrown when invalid arguments are provided
 */
class InvalidArgumentError extends UndiciError {
  name: "InvalidArgumentError";
  code: "UND_ERR_INVALID_ARG";
}

/**
 * Thrown when invalid return values are encountered
 */
class InvalidReturnValueError extends UndiciError {
  name: "InvalidReturnValueError";
  code: "UND_ERR_INVALID_RETURN_VALUE";
}

/**
 * Thrown when functionality is not supported
 */
class NotSupportedError extends UndiciError {
  name: "NotSupportedError";
  code: "UND_ERR_NOT_SUPPORTED";
}

Usage Examples:

import { 
  Client,
  InvalidArgumentError,
  NotSupportedError 
} from "undici-types";

try {
  // This might throw InvalidArgumentError for invalid URL
  const client = new Client("invalid-url");
  
  // This might throw InvalidArgumentError for invalid method
  await client.request({
    path: "/api/data",
    method: "INVALID_METHOD" as any
  });
} catch (error) {
  if (error instanceof InvalidArgumentError) {
    console.error("Invalid argument provided:", error.message);
    // Validate inputs before making requests
  } else if (error instanceof NotSupportedError) {
    console.error("Feature not supported:", error.message);
    // Use alternative approach
  }
}

Pool and Agent Errors

Errors specific to connection pools and agents.

/**
 * Thrown when balanced pool has no available upstreams
 */
class BalancedPoolMissingUpstreamError extends UndiciError {
  name: "BalancedPoolMissingUpstreamError";
  code: "UND_ERR_BPL_MISSING_UPSTREAM";
}

/**
 * Thrown on HTTP parsing errors
 */
class HTTPParserError extends UndiciError {
  name: "HTTPParserError";
  code: "UND_ERR_PARSER";
  bytesParsed: number;
}

/**
 * Thrown on informational status code errors (1xx)
 */
class InformationalError extends UndiciError {
  name: "InformationalError";
  code: "UND_ERR_INFO";
  status: number;
  statusText: string;
  headers: Record<string, string | string[]>;
}

Usage Examples:

import { 
  BalancedPool,
  BalancedPoolMissingUpstreamError,
  HTTPParserError 
} from "undici-types";

// Balanced pool example
const pool = new BalancedPool([]);

try {
  await pool.request({
    path: "/api/data",
    method: "GET"
  });
} catch (error) {
  if (error instanceof BalancedPoolMissingUpstreamError) {
    console.error("No upstreams available in balanced pool");
    // Add upstreams or use fallback
    pool.addUpstream("https://backup.example.com");
  } else if (error instanceof HTTPParserError) {
    console.error("HTTP parsing error:", error.message);
    console.error("Bytes parsed:", error.bytesParsed);
    // Log for debugging malformed responses
  }
}

Retry Errors

Errors related to retry operations.

/**
 * Thrown when request retry fails after all attempts
 */
class RequestRetryError extends UndiciError {
  name: "RequestRetryError";
  code: "UND_ERR_REQ_RETRY";
  statusCode: number;
  data: {
    count: number;
    maxCount: number;
  };
  cause?: Error;
}

Usage Examples:

import { 
  RetryAgent,
  Agent,
  RequestRetryError 
} from "undici-types";

const retryAgent = new RetryAgent(new Agent(), {
  retry: 3,
  maxTimeout: 30000
});

try {
  const response = await retryAgent.request({
    origin: "https://unreliable-api.example.com",
    path: "/api/data",
    method: "GET"
  });
} catch (error) {
  if (error instanceof RequestRetryError) {
    console.error(`Request failed after ${error.data.count} attempts`);
    console.error(`Max attempts: ${error.data.maxCount}`);
    console.error(`Final status: ${error.statusCode}`);
    console.error(`Underlying cause:`, error.cause);
    
    // Handle final failure
    // Maybe try alternative endpoint or return cached data
  }
}

Error Namespace

All errors are also available through the errors namespace:

namespace errors {
  const UndiciError: typeof UndiciError;
  const ConnectTimeoutError: typeof ConnectTimeoutError;
  const HeadersTimeoutError: typeof HeadersTimeoutError;
  const HeadersOverflowError: typeof HeadersOverflowError;
  const BodyTimeoutError: typeof BodyTimeoutError;
  const ResponseError: typeof ResponseError;
  const ResponseStatusCodeError: typeof ResponseStatusCodeError;
  const InvalidArgumentError: typeof InvalidArgumentError;
  const InvalidReturnValueError: typeof InvalidReturnValueError;
  const RequestAbortedError: typeof RequestAbortedError;
  const InformationalError: typeof InformationalError;
  const RequestContentLengthMismatchError: typeof RequestContentLengthMismatchError;
  const ResponseContentLengthMismatchError: typeof ResponseContentLengthMismatchError;
  const ClientDestroyedError: typeof ClientDestroyedError;
  const ClientClosedError: typeof ClientClosedError;
  const SocketError: typeof SocketError;
  const NotSupportedError: typeof NotSupportedError;
  const BalancedPoolMissingUpstreamError: typeof BalancedPoolMissingUpstreamError;
  const HTTPParserError: typeof HTTPParserError;
  const ResponseExceededMaxSizeError: typeof ResponseExceededMaxSizeError;
  const RequestRetryError: typeof RequestRetryError;
  const SecureProxyConnectionError: typeof SecureProxyConnectionError;
}

Usage Examples:

import { errors } from "undici-types";

// Use errors namespace
try {
  // Some HTTP operation
} catch (error) {
  if (error instanceof errors.ConnectTimeoutError) {
    // Handle connection timeout
  } else if (error instanceof errors.ResponseStatusCodeError) {
    // Handle HTTP status errors
  }
}

// Error type checking utility
function isUndiciError(error: unknown): error is UndiciError {
  return error instanceof errors.UndiciError;
}

function handleHttpError(error: unknown) {
  if (!isUndiciError(error)) {
    throw error; // Re-throw non-Undici errors
  }
  
  switch (error.code) {
    case "UND_ERR_CONNECT_TIMEOUT":
      return "Connection timed out - check network connectivity";
    case "UND_ERR_RESPONSE_STATUS_CODE":
      return `HTTP error: ${(error as errors.ResponseStatusCodeError).status}`;
    case "UND_ERR_ABORTED":
      return "Request was cancelled";
    default:
      return `Undici error: ${error.message}`;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-undici-types

docs

connection-management.md

cookies.md

error-handling.md

http-api.md

http-clients.md

index.md

interceptors.md

testing-mocking.md

utilities.md

web-standards.md

tile.json