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
issueswithout exceptions.
Handle Async Schema Errors
The sync helpers reject asynchronous schemas with errors that are not ValidationError:
standardValidateSyncthrows aTypeErrorwith the messageAsync schemas are not supported by standardValidateSync.- Validators from
createStandardValidatorSyncthrow anErrorwith the messageAsync schemas are not supported by createStandardValidatorSync, with the underlyingTypeErroras itscause.
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.