When throwOnError: true is set and the server returns a 4xx/5xx response, the client does not throw an Error instance. Instead, it parses the response body as JSON and throws the resulting plain object directly.
This means:
error instanceof Error → false
error.status → undefined (HTTP status code is lost)
- The only way to identify the error is by inspecting fields like
error.message, which are API-specific and not standardized.
Steps to Reproduce
import { createClient } from '@hey-api/client-fetch';
const client = createClient({ baseUrl: 'https://example.com' });
try {
await client.get({ url: '/protected', throwOnError: true });
} catch (error) {
console.log(error instanceof Error); // ❌ false
console.log(error.status); // ❌ undefined — HTTP status lost!
console.log(error.message); // ✅ e.g. "auth.unauthenticated.wrong_token"
}
Expected Behavior
The thrown value should be (or extend) an Error instance with the HTTP status code attached, similar to the old ApiError from openapi-typescript-codegen (pre-0.32.x):
catch (error) {
error instanceof Error // ✅ true
error.status // ✅ 401, 403, 404, 500, ...
error.body // ✅ parsed JSON body
}
Impact
This is a silent breaking behavior that is especially problematic when:
- Using global error handlers that distinguish errors by HTTP status (e.g. redirect on 401, show 404 page, etc.).
- Using frameworks like Next.js — an unrecognized thrown object that is not an
Error instance can crash the application with a cryptic Digest error message, because error boundaries and middleware expect Error instances.
- Migrating from the legacy client where
ApiError with .status was the standard.
Reproduction
https://stackblitz.com/edit/hey-api-client-fetch-example-99xjbds1?file=src%2FApp.tsx
Environment
@hey-api/client-fetch: latest
When
throwOnError: trueis set and the server returns a 4xx/5xx response, the client does not throw anErrorinstance. Instead, it parses the response body as JSON and throws the resulting plain object directly.This means:
error instanceof Error→falseerror.status→undefined(HTTP status code is lost)error.message, which are API-specific and not standardized.Steps to Reproduce
Expected Behavior
The thrown value should be (or extend) an
Errorinstance with the HTTP status code attached, similar to the oldApiErrorfromopenapi-typescript-codegen(pre-0.32.x):Impact
This is a silent breaking behavior that is especially problematic when:
Errorinstance can crash the application with a cryptic Digest error message, because error boundaries and middleware expectErrorinstances.ApiErrorwith.statuswas the standard.Reproduction
https://stackblitz.com/edit/hey-api-client-fetch-example-99xjbds1?file=src%2FApp.tsx
Environment
@hey-api/client-fetch: latest