Skip to content
Zap Studio
fetch
Esc
navigateopen⌘Jpreview
On this page

Error Handling

Catch FetchError and ValidationError, and handle parsing, abort, and network failures from fetch calls.

fetch throws FetchError for HTTP failures and ValidationError for schema failures. Platform and schema errors can still propagate from native fetch, body parsing, request construction, or the validator itself.

Error Import path Thrown when
FetchError fetch The response is not ok and throwOnFetchError is true (default).
ValidationError validation A schema is provided, validation returns issues, and throwOnValidationError is true (default).
import { FetchError } from "@zap-studio/fetch";
import { ValidationError } from "@zap-studio/validation";

FetchError

Thrown for non-2xx responses before the body is parsed or validated. Its message has the form HTTP <status>: <statusText>.

Property Type Description
status number HTTP status code from the failing response.
response Response Full response object for further inspection (headers, body, …).
import { api, FetchError } from "@zap-studio/fetch";
import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });

try {
  await api.get("https://api.example.com/users/missing", UserSchema);
} catch (error) {
  if (error instanceof FetchError) {
    console.error(error.status);
    console.error(await error.response.text());
  } else {
    throw error;
  }
}

Set throwOnFetchError: false to handle the response manually.

import { $fetch } from "@zap-studio/fetch";

const response = await $fetch("https://api.example.com/users/missing", {
  throwOnFetchError: false,
});

if (!response.ok) {
  console.error(response.status);
}

ValidationError

Thrown when the response body does not match the provided schema. Its message is a JSON string of the issues.

Property Type Description
issues readonly StandardSchemaV1.Issue[] Validation issues reported by the schema.
import { api } from "@zap-studio/fetch";
import { ValidationError } from "@zap-studio/validation";
import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });

try {
  await api.get("https://api.example.com/users/1", UserSchema);
} catch (error) {
  if (error instanceof ValidationError) {
    console.error(error.issues);
  } else {
    throw error;
  }
}

Set throwOnValidationError: false to receive the Standard Schema result object instead.

import { api } from "@zap-studio/fetch";
import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });

const result = await api.get("https://api.example.com/users/1", UserSchema, {
  throwOnValidationError: false,
});

if (result.issues) {
  console.error(result.issues);
}

See Validation for the full validation flow.

Other Throwable Errors

Calls can also reject with:

  • TypeError — both body and json provided, invalid headers or search params, request construction failure, JSON request serialization failure, network failure, or a response body read failure.
  • SyntaxError — a schema is provided and response.json() cannot parse the body.
  • DOMException — the request or response body read is aborted (AbortError).
  • Any error thrown or rejected by the provided Standard Schema validator.

Exhaustive Handling

Catch package-specific errors first, then rethrow unknown failures.

import { api, FetchError } from "@zap-studio/fetch";
import { ValidationError } from "@zap-studio/validation";
import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });

async function loadUser(id: string) {
  try {
    const user = await api.get(`https://api.example.com/users/${id}`, UserSchema);
    return { ok: true as const, user };
  } catch (error) {
    if (error instanceof FetchError) {
      return { ok: false as const, reason: "http", status: error.status };
    }

    if (error instanceof ValidationError) {
      return { ok: false as const, reason: "validation", issues: error.issues };
    }

    throw error;
  }
}

Last updated on September 15, 2026

Was this page helpful?