Core Concepts

Error Handling

Rezo throws RezoError instances for all failures: network errors, HTTP errors, timeouts, proxy issues, TLS problems, and more. Each error carries a structured error code, boolean classification flags, and the original request configuration.

Basic Usage

import rezo, { RezoError } from 'rezo';

try {
  const response = await rezo.get('https://api.example.com/data');
} catch (error) {
  if (error instanceof RezoError) {
    console.log(error.code);       // "REZ_HTTP_ERROR"
    console.log(error.status);     // 404
    console.log(error.message);    // "Request failed with status code 404"
    console.log(error.suggestion); // "Check the status code and response body..."
  }
}

RezoError Properties

code

RezoErrorCodeString — The error code identifying the failure type. Provides full IDE autocomplete for all known codes while still accepting unknown OS/runtime error codes.

if (error.code === 'ECONNREFUSED') {
  console.log('Server is down');
}

// Also available via the enum
import { RezoErrorCode } from 'rezo';
if (error.code === RezoErrorCode.CONNECTION_REFUSED) {
  console.log('Server is down');
}

config

RezoConfig — The request configuration that produced the error.

console.log(error.config.url);
console.log(error.config.method);

request

RezoHttpRequest | undefined — The request object, when available.

response

RezoResponse<T> | undefined — The server response, when available (only for HTTP errors where the server responded).

if (error.response) {
  console.log(error.response.status);     // 403
  console.log(error.response.data);       // Error body from server
  console.log(error.response.headers);    // Response headers
}

status

number | undefined — The HTTP status code. Only defined when the error includes a response.

if (error.status === 429) {
  console.log('Rate limited, retry later');
}

statusText

string | undefined — The HTTP status text (e.g., "Not Found"). Only defined when the error includes a response.

suggestion

string — A human-readable recovery suggestion for the error code. Useful for logging and debugging.

console.log(error.suggestion);
// "Verify the server is running and accessible. Check firewall rules..."

Boolean Classification Flags

Every RezoError carries boolean flags for fast classification. These are non-enumerable (they do not clutter console.log output) but are always accessible.

isTimeout

true when the error is a timeout: ETIMEDOUT, UND_ERR_CONNECT_TIMEOUT, UND_ERR_HEADERS_TIMEOUT, UND_ERR_REQUEST_TIMEOUT, ERR_TLS_HANDSHAKE_TIMEOUT, REZ_PROXY_TIMEOUT.

if (error.isTimeout) {
  console.log('Request timed out, consider increasing timeout');
}

isAborted

true when the request was explicitly aborted: ABORT_ERR, UND_ERR_ABORTED.

if (error.isAborted) {
  console.log('Request was cancelled');
}

isNetworkError

true for low-level network failures: ECONNREFUSED, ECONNRESET, ENOTFOUND, EAI_AGAIN, EPIPE, EHOSTUNREACH, ENETUNREACH, UND_ERR_SOCKET.

if (error.isNetworkError) {
  console.log('Network problem, check connectivity');
}

isHttpError

true when the server responded with a non-successful status code (REZ_HTTP_ERROR). The response property is always set for HTTP errors.

if (error.isHttpError) {
  console.log(`Server returned ${error.status}: ${error.response?.data}`);
}

isProxyError

true for proxy-related failures: REZ_PROXY_CONNECTION_FAILED, REZ_PROXY_AUTHENTICATION_FAILED, REZ_PROXY_TARGET_UNREACHABLE, REZ_PROXY_ERROR, REZ_PROXY_TIMEOUT, REZ_PROXY_INVALID_PROTOCOL, REZ_PROXY_INVALID_HOSTPORT.

if (error.isProxyError) {
  console.log('Proxy failure, try a different proxy');
}

isSocksError

true for SOCKS proxy failures: REZ_SOCKS_CONNECTION_FAILED, REZ_SOCKS_AUTHENTICATION_FAILED, REZ_SOCKS_TARGET_CONNECTION_FAILED, REZ_SOCKS_PROTOCOL_ERROR, REZ_SOCKS_UNSUPPORTED_VERSION.

if (error.isSocksError) {
  console.log('SOCKS proxy issue');
}

isTlsError

true for TLS/SSL failures: EPROTO, ERR_TLS_CERT_ALTNAME_INVALID, ERR_TLS_HANDSHAKE_TIMEOUT, ERR_TLS_INVALID_PROTOCOL_VERSION, ERR_TLS_RENEGOTIATION_DISABLED, ERR_TLS_CERT_SIGNATURE_ALGORITHM_UNSUPPORTED, CERT_HAS_EXPIRED, UNABLE_TO_VERIFY_LEAF_SIGNATURE, SELF_SIGNED_CERT_IN_CHAIN, DEPTH_ZERO_SELF_SIGNED_CERT.

if (error.isTlsError) {
  console.log('Certificate or TLS problem');
}

isRetryable

true when the error is safe to retry: all timeout codes plus ECONNRESET, ECONNREFUSED, EAI_AGAIN, REZ_RATE_LIMITED, and REZ_HTTP_ERROR.

if (error.isRetryable) {
  // Safe to retry this request
}

Static Factories

RezoError provides static factory methods for creating specific error types. These are primarily used internally by adapters but are available for testing and custom adapter development.

RezoError.createHttpError(statusCode, config, request?, response?)

Creates an HTTP error with status code, method, URL, and redirect chain information.

const error = RezoError.createHttpError(404, config, request, response);
// error.code === 'REZ_HTTP_ERROR'
// error.status === 404
// error.statusText === 'Not Found'

RezoError.createNetworkError(message, code, config, request?)

Creates a network-level error with a specific error code.

const error = RezoError.createNetworkError('Connection failed', 'ECONNREFUSED', config);

RezoError.createTimeoutError(message, config, request?)

Creates a timeout error with code ETIMEDOUT.

const error = RezoError.createTimeoutError('Request timed out after 5000ms', config);

RezoError.createAbortError(message, config, request?)

Creates an abort error with code ABORT_ERR.

RezoError.createParsingError(message, config, request?)

Creates a JSON parsing error with code REZ_INVALID_JSON.

RezoError.createDecompressionError(message, config, request?, response?)

Creates a decompression error with code REZ_DECOMPRESSION_ERROR.

RezoError.createDownloadError(message, config, request?, response?)

Creates a download failure with code REZ_DOWNLOAD_FAILED.

RezoError.createUploadError(message, config, request?, response?)

Creates an upload failure with code REZ_UPLOAD_FAILED.

RezoError.createStreamError(message, config, request?, response?)

Creates a stream error with code REZ_STREAM_ERROR.

RezoError.createRedirectError(message, config, request?, response?)

Creates a redirect error with code REZ_MISSING_REDIRECT_LOCATION.

RezoError.createProxyError(code, config, request?)

Creates a proxy error. The code must be a valid proxy error code; invalid codes fall back to REZ_PROXY_ERROR.

RezoError.createSocksError(code, config, request?)

Creates a SOCKS proxy error. Invalid codes fall back to REZ_SOCKS_CONNECTION_FAILED.

RezoError.createTlsError(code, config, request?)

Creates a TLS error. Invalid codes fall back to EPROTO.

RezoError.createRateLimitError(config, request?, response?)

Creates a rate-limit error with code REZ_RATE_LIMITED and status 429.

RezoError.fromError(error, config, request?, response?)

Wraps any Error instance into a RezoError, preserving the original error as cause and extracting OS-level properties (syscall, hostname, port, address).

try {
  // some operation
} catch (err) {
  throw RezoError.fromError(err, config);
}

Type Guard

isRezoError(error)

A type guard function that checks if a value is a RezoError. Works across module boundaries where instanceof may fail.

import { isRezoError } from 'rezo';

try {
  await rezo.get('https://api.example.com/data');
} catch (error) {
  if (isRezoError(error)) {
    // error is typed as RezoError
    console.log(error.code);
  }
}

Also available as a static method:

RezoError.isRezoError(error);

Serialization

toJSON()

Returns a clean JSON representation with only defined values. Includes: name, message, code, method, url, finalUrl, status, statusText, urls, and cause.

console.log(JSON.stringify(error.toJSON(), null, 2));
// {
//   "name": "RezoError",
//   "message": "Request failed with status code 404",
//   "code": "REZ_HTTP_ERROR",
//   "method": "GET",
//   "url": "https://api.example.com/missing",
//   "status": 404,
//   "statusText": "Not Found"
// }

toString()

Returns a concise string representation.

console.log(error.toString());
// "RezoError: Request failed with status code 404 [REZ_HTTP_ERROR]"

getFullDetails()

Returns a multi-line diagnostic string with all available information, including the redirect chain and recovery suggestion.

console.log(error.getFullDetails());
// RezoError: Request failed with status code 404
// Code: REZ_HTTP_ERROR
// Method: GET
// URL: https://api.example.com/missing
// HTTP Status: 404 Not Found
//
// Suggestion: Check the status code and response body for more details about the error.

ERROR_INFO Reference

The ERROR_INFO map contains metadata for every known error code. Each entry provides a human-readable message, a detailed explanation, and a recovery suggestion.

Network and OS Errors

CodeMessage
ECONNREFUSEDConnection Refused
ECONNRESETConnection Reset
ECONNABORTEDConnection Aborted
ETIMEDOUTConnection Timeout
ESOCKETTIMEDOUTSocket Timeout
ENOTFOUNDDNS Lookup Failed
EAI_AGAINTemporary DNS Failure
EHOSTUNREACHHost Unreachable
ENETUNREACHNetwork Unreachable
EPIPEBroken Pipe

HTTP Errors

CodeMessage
REZ_HTTP_ERRORHTTP Error
REZ_REDIRECT_DENIEDRedirect Denied
REZ_MAX_REDIRECTS_EXCEEDEDMaximum Redirects Exceeded
REZ_REDIRECT_CYCLE_DETECTEDRedirect Cycle Detected
REZ_MISSING_REDIRECT_LOCATIONMissing Redirect Location
REZ_DECOMPRESSION_ERRORDecompression Error
REZ_RATE_LIMITEDRate Limited
REZ_INVALID_JSONInvalid JSON Response

Stream and Transfer Errors

CodeMessage
REZ_DOWNLOAD_FAILEDDownload Failed
REZ_UPLOAD_FAILEDUpload Failed
REZ_STREAM_ERRORStream Error
REZ_BODY_TOO_LARGERequest Body Too Large
REZ_RESPONSE_TOO_LARGEResponse Too Large
ERR_STREAM_DESTROYEDStream Destroyed
ERR_STREAM_PREMATURE_CLOSEPremature Stream Close

Proxy Errors

CodeMessage
REZ_PROXY_CONNECTION_FAILEDProxy Connection Failed
REZ_PROXY_AUTHENTICATION_FAILEDProxy Authentication Failed
REZ_PROXY_TARGET_UNREACHABLEProxy Target Unreachable
REZ_PROXY_ERRORProxy Error
REZ_PROXY_TIMEOUTProxy Timeout
REZ_PROXY_INVALID_PROTOCOLInvalid Proxy Protocol
REZ_PROXY_INVALID_HOSTPORTInvalid Proxy Configuration
REZ_NO_PROXY_AVAILABLENo Proxy Available

SOCKS Proxy Errors

CodeMessage
REZ_SOCKS_CONNECTION_FAILEDSOCKS Proxy Connection Failed
REZ_SOCKS_AUTHENTICATION_FAILEDSOCKS Proxy Authentication Failed
REZ_SOCKS_TARGET_CONNECTION_FAILEDSOCKS Proxy Target Unreachable
REZ_SOCKS_PROTOCOL_ERRORSOCKS Protocol Error
REZ_SOCKS_UNSUPPORTED_VERSIONSOCKS Version Not Supported

TLS / SSL Errors

CodeMessage
EPROTOProtocol Error
ERR_TLS_CERT_ALTNAME_INVALIDCertificate Hostname Mismatch
ERR_TLS_HANDSHAKE_TIMEOUTTLS Handshake Timeout
ERR_TLS_INVALID_PROTOCOL_VERSIONTLS Protocol Version Mismatch
ERR_TLS_RENEGOTIATION_DISABLEDTLS Renegotiation Disabled
ERR_TLS_CERT_SIGNATURE_ALGORITHM_UNSUPPORTEDUnsupported Certificate Signature
CERT_HAS_EXPIREDCertificate Expired
UNABLE_TO_VERIFY_LEAF_SIGNATURECertificate Verification Failed
SELF_SIGNED_CERT_IN_CHAINSelf-Signed Certificate
DEPTH_ZERO_SELF_SIGNED_CERTSelf-Signed Certificate (No Chain)

Timeout and Abort Errors

CodeMessage
UND_ERR_CONNECT_TIMEOUTConnect Timeout
UND_ERR_HEADERS_TIMEOUTHeaders Timeout
UND_ERR_REQUEST_TIMEOUTRequest Timeout
ABORT_ERRRequest Aborted
UND_ERR_ABORTEDRequest Aborted
ERR_ABORTEDRequest Aborted

Validation Errors

CodeMessage
ERR_INVALID_URLInvalid URL
ERR_INVALID_PROTOCOLInvalid URL Protocol
ERR_INVALID_ARG_TYPEInvalid Argument Type
REZ_FILE_PERMISSION_ERRORFile Permission Error

Other

CodeMessage
REZ_UNKNOWN_ERRORUnknown Error
ERR_HTTP_HEADERS_SENTHeaders Already Sent
UND_ERR_SOCKETSocket Error
UND_ERR_INFOInvalid Request Info

RezoErrorCode Enum

For type-safe code comparisons, use the RezoErrorCode enum:

import { RezoErrorCode } from 'rezo';

switch (error.code) {
  case RezoErrorCode.CONNECTION_REFUSED:
    console.log('Server is not running');
    break;
  case RezoErrorCode.DNS_LOOKUP_FAILED:
    console.log('Invalid hostname');
    break;
  case RezoErrorCode.HTTP_ERROR:
    console.log(`HTTP ${error.status}`);
    break;
  case RezoErrorCode.PROXY_CONNECTION_FAILED:
    console.log('Proxy is down');
    break;
  case RezoErrorCode.CERTIFICATE_EXPIRED:
    console.log('SSL certificate has expired');
    break;
}

Practical Patterns

Categorized Error Handler

try {
  const response = await rezo.get('https://api.example.com/data');
} catch (error) {
  if (!isRezoError(error)) throw error;

  if (error.isHttpError) {
    switch (error.status) {
      case 401: return redirectToLogin();
      case 403: return showForbidden();
      case 404: return showNotFound();
      case 429: return retryAfterDelay(error);
      default:  return showServerError(error);
    }
  }

  if (error.isTimeout) {
    return showTimeoutMessage();
  }

  if (error.isNetworkError) {
    return showOfflineMessage();
  }

  if (error.isProxyError || error.isSocksError) {
    return rotateProxy();
  }

  if (error.isTlsError) {
    return showCertificateWarning();
  }

  throw error;
}

Logging Errors

catch (error) {
  if (isRezoError(error)) {
    // Structured log for monitoring
    logger.error({
      ...error.toJSON(),
      suggestion: error.suggestion,
      retryable: error.isRetryable
    });

    // Detailed diagnostic for debugging
    if (process.env.DEBUG) {
      console.error(error.getFullDetails());
    }
  }
}