← Docs

Error Handling

The fixed set of per-status HttpError subclasses your generated TypeScript client throws, and how handleHttpError picks one.

This page covers the hosted CodeForge engine only. It documents what your generated TypeScript client throws for a non-OK response — not the OSS The Codegen Project CLI, which has its own docs.

What triggers this

Nothing to configure. Any document that generates an http_client protocol gets the fixed set of error classes below, whether or not your OpenAPI document declares any of these statuses. The class names stay stable across spec changes, since they never depend on what your document declares.

The fixed set

ClassStatus
BadRequestError400
AuthenticationError401
PermissionDeniedError403
NotFoundError404
ConflictError409
UnprocessableEntityError422
RateLimitError429
InternalServerErrorany status >= 500

Every class extends the same HttpError your client already throws, carrying status, statusText, and the parsed response body (typed unknown on every class — the generator does not attempt to type an error body per operation). Each exact-status class narrows status to its literal (readonly status: 404 on NotFoundError); InternalServerError keeps status: number, since the class covers a whole range rather than one code — check status to tell a 500 from a 503.

A status outside this fixed set — 402, 410, or any other 4xx the set does not name — still throws plain HttpError.

How the class is picked

handleHttpError picks the class from the live response status, independent of which statuses your OpenAPI document declares:

  1. An exact match against the fixed set above.
  2. Any other status >= 500 becomes InternalServerError.
  3. Anything else becomes plain HttpError.

A server returning a status your document never declared — a 429 on an operation with no documented rate limit — still gets RateLimitError. Only the error message varies by declaration: a status your document documents gets the documented reason phrase; an undeclared one gets a generic HTTP Error: <status> <statusText> message. The class thrown never depends on that distinction.

Catching errors

Every subclass is also an instanceof HttpError, so an existing catch-all keeps working unchanged. Both HttpError and every subclass import directly from your generated package's root, alongside the client class — no subpath needed. Narrow first when you need to handle one status differently:

import { HttpError, NotFoundError } from 'your-sdk'

try {
	await client.getPet({ parameters: { petId: '1' } })
} catch (error) {
	if (error instanceof NotFoundError) {
		// error.status is narrowed to 404
	} else if (error instanceof HttpError) {
		// any other non-OK response — error.status is number
	}
	throw error
}

What this does not cover

  • Typed error bodies. body stays unknown on every class. Precise per-operation error body types would need a union type derived from each operation's declared error responses — a named non-goal, since one operation can declare a different body shape per status.
  • Classes for declared statuses outside the fixed set. A document declaring 418 still gets plain HttpError for it — the fixed set does not grow to match your document.
  • Connection-level failures, such as a request that times out or never reaches the server at all. Those are a separate concern from a non-OK response and are not one of these classes.