October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk3 min

How to Handle Fetch Errors in TypeScript When the Server Returns a Non-2xx Status

A non-2xx response still resolves from fetch(). Check response.ok before parsing, preserve the body, and distinguish HTTP errors from rejected requests in TypeScript.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A 404 or 500 response does not normally make fetch() reject. It resolves with a Response, so check response.ok or response.status yourself and handle the response before parsing it as successful data. That is why a .catch() handler alone will not catch an HTTP error.

Why doesn’t fetch throw on a 404?

Fetch separates receiving an HTTP response from failing to make a request. If the server replies with a status such as 404 or 500, the promise normally fulfills with a Response. The ok property is true for status codes in the 200 range; status contains the numeric HTTP status.

As an Amazon Associate I earn from qualifying purchases.

A rejected Fetch promise is a different path, such as a network-level failure. Handle both paths deliberately: inspect the response for HTTP failures, and use try/catch for rejected requests and errors thrown while processing the response. See MDN’s Using the Fetch API.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check the status before parsing successful data

If you call response.json() first, parsing may fail when the server’s error body is plain text, empty, or otherwise not valid JSON. That parse error can obscure the more useful fact that the server returned an HTTP failure. Read the body once, check the status, and parse it as JSON only when appropriate.

export class HttpError extends Error {
  constructor(
    public readonly status: number,
    public readonly statusText: string,
    public readonly body: string,
  ) {
    super(`HTTP ${status}: ${statusText}`);
    this.name = "HttpError";
  }
}

export async function fetchJson<T>(
  input: RequestInfo | URL,
  init?: RequestInit,
): Promise<T> {
  const response = await fetch(input, init);
  const body = await response.text();

  if (!response.ok) {
    throw new HttpError(response.status, response.statusText, body);
  }

  if (body.length === 0) {
    throw new Error("Expected a JSON response body, but received an empty body.");
  }

  return JSON.parse(body) as T;
}

try {
  const user = await fetchJson<{ id: string; name: string }>("/api/user");
  console.log(user.name);
} catch (error: unknown) {
  if (error instanceof HttpError) {
    console.error("HTTP response failed:", error.status, error.body);
  } else if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error("Unexpected thrown value", error);
  }
}

This helper treats an empty successful body as an error because it expects JSON. Change that behavior for endpoints that legitimately return no content. Also, as T is only a TypeScript assertion: it does not verify that the parsed JSON actually has the shape of T. Validate untrusted response data with an application schema or type guard before relying on its structure.

Read error bodies without assuming they are JSON

Response body readers such as text() and json() are asynchronous, and a response body should not be consumed twice. Reading with text() lets the helper retain plain-text or malformed error content for diagnostics. If an API documents structured JSON errors, inspect the response content type and parse accordingly; servers, proxies, and gateways do not all use the same error format. Preserve the HTTP status even if a body is missing or cannot be parsed. MDN documents the Response body-reading methods and status properties.

Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Choose whether HTTP errors should throw

A custom error is useful when callers should use one exception path and need to branch on status or inspect the response body. The HttpError example above preserves those details and lets callers distinguish an HTTP response failure with instanceof.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If an HTTP error is expected control flow, return a discriminated result instead, so callers must handle success and failure explicitly without throwing:

type FetchResult<T> =
  | { ok: true; data: T }
  | { ok: false; status: number; body: string };

Whichever style you choose, keep the status and useful body details available to the code that decides what to do next.

Use TypeScript’s catch variable safely

TypeScript does not change Fetch’s runtime behavior; it affects how values are typed in your code. With useUnknownInCatchVariables enabled—which is part of the strict family of options—catch variables are unknown. Narrow them before reading properties such as message, for example with error instanceof Error or a check for your own HttpError class. The TypeScript 4.4 release notes document this behavior.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Do not retry every non-2xx response automatically

A non-2xx status alone does not establish that a retry is safe or useful. Decide based on the endpoint’s semantics, status, request method, idempotency, and any server guidance. A received HTTP error response and a rejected Fetch promise are distinct conditions; neither implies a universal retry policy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.