Skip to main content

HttpError

An error class thrown for all request failures. Extends Error.

import { HttpError, isHttpError } from '@parcely/core'

Class definition

class HttpError extends Error {
readonly code: HttpErrorCode
readonly status: number | undefined
readonly config: RequestConfig
readonly response: HttpResponse<unknown> | undefined
readonly cause: unknown

/** JSON-safe serialisation for structured logging. See below. */
toJSON(): HttpErrorJSON
}

HttpErrorJSON — structured logging

HttpError.toJSON() returns a HttpErrorJSON object that JSON.stringify produces automatically. Unlike the live error, this is guaranteed safe to serialise: Headers instances are flattened to Record<string, string>, cause is reduced to { name, message, code } (no circular-reference throws), and response contains only primitives.

import type { HttpErrorJSON } from '@parcely/core'

try {
await http.get('/u')
} catch (e) {
if (e instanceof HttpError) {
logger.error(JSON.stringify(e))
// ^^^^^^^^^^^^^^^^^^^^^^ HttpErrorJSON
}
}

Fields: name, message, code, optional status, config (method/url/baseURL/headers/params/timeout), optional response (status/statusText/headers/data), optional cause ({ name, message, code }), optional stack. Strip stack before sending to untrusted endpoints.

Fields

FieldTypeDescription
codeHttpErrorCodeMachine-readable error code. See table below.
statusnumber | undefinedHTTP status code, if a response was received.
configRequestConfigThe merged request config with sensitive headers redacted.
responseHttpResponse<unknown> | undefinedThe response envelope, if a response was received.
causeunknownThe underlying error (e.g., TypeError from fetch, SyntaxError from JSON parse, validation error).

Error codes

CodeWhen thrown
ERR_HTTP_STATUSNon-2xx response (status code outside 200--299).
ERR_NETWORKNetwork-level failure: DNS error, connection refused, TLS error, stream error.
ERR_TIMEOUTThe request timeout elapsed.
ERR_ABORTEDThe user's AbortSignal was triggered.
ERR_TOO_MANY_REDIRECTSRedirect count exceeded maxRedirects.
ERR_DISALLOWED_PROTOCOLURL scheme not in allowedProtocols.
ERR_DISALLOWED_HEADERHeader name not in allowedRequestHeaders (when set).
ERR_ABSOLUTE_URLAbsolute URL used when baseURL is set and allowAbsoluteUrls is false.
ERR_PARSEResponse body could not be parsed (e.g., invalid JSON).
ERR_VALIDATIONThe validate function/schema rejected the response body.
ERR_CRLF_INJECTIONA header name or value contains CRLF characters.

isHttpError type guard

function isHttpError(value: unknown): value is HttpError

Returns true if the value is an instance of HttpError.

Example

import { createClient, isHttpError } from '@parcely/core'

const http = createClient({ baseURL: 'https://api.example.com' })

try {
await http.get('/users/999')
} catch (err) {
if (isHttpError(err)) {
switch (err.code) {
case 'ERR_HTTP_STATUS':
console.log(`HTTP ${err.status}: ${err.response?.data}`)
break
case 'ERR_TIMEOUT':
console.log('Request timed out')
break
case 'ERR_NETWORK':
console.log('Network error:', err.cause)
break
case 'ERR_VALIDATION':
console.log('Response validation failed:', err.cause)
break
default:
console.log(`Error: ${err.code}`)
}
}
}

HttpErrorCode type

type HttpErrorCode =
| 'ERR_HTTP_STATUS'
| 'ERR_NETWORK'
| 'ERR_TIMEOUT'
| 'ERR_ABORTED'
| 'ERR_TOO_MANY_REDIRECTS'
| 'ERR_DISALLOWED_PROTOCOL'
| 'ERR_DISALLOWED_HEADER'
| 'ERR_ABSOLUTE_URL'
| 'ERR_PARSE'
| 'ERR_VALIDATION'
| 'ERR_CRLF_INJECTION'

HttpErrorOptions

The constructor options for HttpError:

interface HttpErrorOptions {
code: HttpErrorCode
status?: number
config: RequestConfig
response?: HttpResponse<unknown>
cause?: unknown
}
FieldTypeDescription
codeHttpErrorCodeThe error code.
statusnumber | undefinedHTTP status code, if applicable.
configRequestConfigThe request config (will be redacted).
responseHttpResponse<unknown> | undefinedThe response envelope, if received.
causeunknownThe underlying cause.

See also