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

Errors

Optional throwing behavior via throwOnError, backed by a shared ValidationError class.

throwOnError enables optional throwing, backed by a shared ValidationError class. Instead of dealing with each schema library’s error shape, you catch one predictable error class and access normalized Standard Schema issues.

Know When ValidationError Is Thrown

ValidationError is thrown only in throwing mode, by:

  • standardValidate(input, schema, { throwOnError: true })
  • standardValidateSync(input, schema, { throwOnError: true })
  • validators from createStandardValidator(schema) called with { throwOnError: true }
  • validators from createStandardValidatorSync(schema) called with { throwOnError: true }

When throwOnError is false or omitted, the helpers never throw for invalid input — they return the raw result with issues instead.

Catch ValidationError

Import ValidationError from validation and check with instanceof.

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

const userSchema = z.object({
  name: z.string(),
  age: z.number(),
});

try {
  const user = await standardValidate(input, userSchema, {
    throwOnError: true,
  });

  // use user
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Validation failed", error.issues);
    return;
  }

  throw error;
}

Inspect the Error

ValidationError extends Error and exposes:

Property Type Description
name string Always "ValidationError".
issues readonly StandardSchemaV1.Issue[] The validation issues reported by the schema. Each issue has a message and an optional path.
message string A JSON string representation of issues, useful for logging.
if (error instanceof ValidationError) {
  for (const issue of error.issues) {
    console.error(issue.path, issue.message);
  }
}

Handle Failures Without Exceptions

Use non-throwing mode when validation failures are expected and part of normal logic, such as form workflows where you return field errors instead of throwing.

import { standardValidate } from "@zap-studio/validation";
import { z } from "zod";

const emailSchema = z.object({
  email: z.email(),
});

const result = await standardValidate(formData, emailSchema);

if (result.issues) {
  return { ok: false, fieldErrors: result.issues };
}

return { ok: true, value: result.value };

As a rule of thumb:

  • Use throwing mode when invalid input should interrupt control flow immediately, or when your layer already handles exceptions (API handlers, service boundaries).
  • Use non-throwing mode when you want explicit branching on issues without exceptions.

Handle Async Schema Errors

The sync helpers reject asynchronous schemas with errors that are not ValidationError:

  • standardValidateSync throws a TypeError with the message Async schemas are not supported by standardValidateSync.
  • Validators from createStandardValidatorSync throw an Error with the message Async schemas are not supported by createStandardValidatorSync, with the underlying TypeError as its cause.

These indicate a programming error (wrong helper for the schema), so let them propagate rather than catching them alongside validation failures. Switch to standardValidate if the schema may validate asynchronously.

See Also

Last updated on September 13, 2026

Was this page helpful?