zaggino/z-schema/handling-validation-errors

Claude Code and agent skill by zaggino/z-schema

Trust tier 2
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Inspects, filters, and maps z-schema validation errors for application use. Use when the user needs to handle validation errors, walk nested inner errors from anyOf/oneOf/not combinators, map error codes to user-friendly messages, filter errors with includeErrors or excludeErrors, build form-field error mappers, use reportPathAsArray, interpret SchemaErrorDetail fields like code/path/keyword/inner, or debug why validation failed.

Install

npx vskill@latest install zaggino/z-schema/handling-validation-errors

SKILL.md

Handling Validation Errors in z-schema

z-schema reports validation errors as ValidateError objects containing a .details array of SchemaErrorDetail. This skill covers inspecting, filtering, mapping, and presenting these errors.

Error structure

typescript
import type { SchemaErrorDetail } from 'z-schema';
import { ValidateError } from 'z-schema';

ValidateError extends Error:

PropertyTypeDescription
.namestringAlways 'ValidateError'
.messagestringSummary message
.detailsSchemaErrorDetail[]All individual errors

Each SchemaErrorDetail:

FieldTypeDescription
messagestringHuman-readable text, e.g. "Expected type string but found type number"
codestringMachine-readable code, e.g. "INVALID_TYPE"
params`(string \number \Array)[]`Values filling the message template placeholders
path`string \Array<string \number>`JSON Pointer to the failing value ("#/age" or ["age"])
keywordstring?Schema keyword that caused the error ("type", "required", etc.)
innerSchemaErrorDetail[]?Sub-errors from combinators (anyOf, oneOf, not)
schemaPath`Array<string \number>?`Path within the schema to the constraint
schemaIdstring?Schema ID if present
titlestring?Schema title if present
descriptionstring?Schema description if present

Capturing errors

Try/catch (default mode)
typescript
import ZSchema from 'z-schema';
const validator = ZSchema.create();
try {
validator.validate(data, schema);
} catch (err) {
if (err instanceof ValidateError) {
for (const detail of err.details) {
console.log(`[${detail.code}] ${detail.path}: ${detail.message}`);
}
}
}
Safe mode (no try/catch)
typescript
const validator = ZSchema.create();
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
for (const detail of err.details) {
console.log(`[${detail.code}] ${detail.path}: ${detail.message}`);
}
}

Walking nested errors

Combinators (anyOf, oneOf, not) produce nested inner errors. A recursive walker handles any depth:

typescript
function walkErrors(details: SchemaErrorDetail[], depth = 0): void {
for (const detail of details) {
const indent = ' '.repeat(depth);
console.log(`${indent}[${detail.code}] ${detail.path}: ${detail.message}`);
if (detail.inner) {
walkErrors(detail.inner, depth + 1);
}
}
}
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
walkErrors(err.details);
}
Collecting all leaf errors

Flatten the tree to get every concrete error, skipping combinator wrappers:

typescript
function collectLeafErrors(details: SchemaErrorDetail[]): SchemaErrorDetail[] {
const leaves: SchemaErrorDetail[] = [];
for (const detail of details) {
if (detail.inner && detail.inner.length > 0) {
leaves.push(...collectLeafErrors(detail.inner));
} else {
leaves.push(detail);
}
}
return leaves;
}

Mapping errors to form fields

Convert JSON Pointer paths to field names for UI form validation:

typescript
function pathToFieldName(path: string | Array<string | number>): string {
if (Array.isArray(path)) {
return path.join('.');
}
// JSON Pointer string: "#/address/city" → "address.city"
return path.replace(/^#\/?/, '').replace(/\//g, '.');
}
function errorsToFieldMap(details: SchemaErrorDetail[]): Record<string, string[]> {
const map: Record<string, string[]> = {};
const leaves = collectLeafErrors(details);
for (const detail of leaves) {
const field = pathToFieldName(detail.path) || '_root';
(map[field] ??= []).push(detail.message);
}
return map;
}
// Usage
const { valid, err } = validator.validateSafe(formData, schema);
if (!valid && err) {
const fieldErrors = errorsToFieldMap(err.details);
// { "email": ["Expected type string but found type number"],
// "age": ["Value 150 is greater than maximum 120"] }
}
Using array paths

Enable reportPathAsArray for easier programmatic access:

typescript
const validator = ZSchema.create({ reportPathAsArray: true });
const { valid, err } = validator.validateSafe(data, schema);
// err.details[0].path → ["address", "city"] instead of "#/address/city"

Filtering errors

Per-call filtering

Pass includeErrors or excludeErrors as the third argument:

typescript
// Only report type mismatches
validator.validate(data, schema, { includeErrors: ['INVALID_TYPE'] });
// Suppress string-length errors
validator.validate(data, schema, { excludeErrors: ['MIN_LENGTH', 'MAX_LENGTH'] });
Programmatic post-filtering
typescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
const typeErrors = err.details.filter((d) => d.code === 'INVALID_TYPE');
const requiredErrors = err.details.filter((d) => d.code === 'OBJECT_MISSING_REQUIRED_PROPERTY');
}

Custom error messages

Map error codes to user-friendly messages:

typescript
const friendlyMessages: Record<string, (detail: SchemaErrorDetail) => string> = {
INVALID_TYPE: (d) => `${pathToFieldName(d.path)} must be a ${d.params[0]}`,
OBJECT_MISSING_REQUIRED_PROPERTY: (d) => `${d.params[0]} is required`,
MINIMUM: (d) => `${pathToFieldName(d.path)} must be at least ${d.params[1]}`,
MAXIMUM: (d) => `${pathToFieldName(d.path)} must be at most ${d.params[1]}`,
MIN_LENGTH: (d) => `${pathToFieldName(d.path)} must be at least ${d.params[1]} characters`,
MAX_LENGTH: (d) => `${pathToFieldName(d.path)} must be at most ${d.params[1]} characters`,
PATTERN: (d) => `${pathToFieldName(d.path)} has an invalid format`,
ENUM_MISMATCH: (d) => `${pathToFieldName(d.path)} must be one of the allowed values`,
INVALID_FORMAT: (d) => `${pathToFieldName(d.path)} is not a valid ${d.params[0]}`,
ARRAY_UNEVALUATED_ITEMS: () => `Array contains items not covered by any schema`,
OBJECT_UNEVALUATED_PROPERTIES: (d) => `${d.params[0]} is not allowed by the schema`,
COLLECT_EVALUATED_DEPTH_EXCEEDED: (d) => `Schema nesting too deep (max ${d.params[0]})`,
MAX_RECURSION_DEPTH_EXCEEDED: (d) => `Recursion depth exceeded (max ${d.params[0]})`,
};
function toFriendlyMessage(detail: SchemaErrorDetail): string {
const fn = friendlyMessages[detail.code];
return fn ? fn(detail) : detail.message;
}

Stopping at first error

For fail-fast scenarios:

typescript
const validator = ZSchema.create({ breakOnFirstError: true });

This reports only the first error encountered, reducing noise during iterative fixing.

Using the keyword field

The keyword field tells you which schema keyword triggered the error — useful for categorizing errors programmatically:

typescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
for (const detail of err.details) {
switch (detail.keyword) {
case 'required':
// handle missing field
break;
case 'type':
// handle type mismatch
break;
case 'format':
// handle format failure
break;
}
}
}

Reference files

For the full error code list with descriptions, see the validating-json-data skill's error-codes reference.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
350
Repository forks
91
Repository npm downloads, 7 days
2,848,839
7-day trend score
62

Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 16 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/zaggino/z-schema/handling-validation-errors/badge)](https://verified-skill.com/skills/zaggino/z-schema/handling-validation-errors)

Something wrong with this skill or its page? Tell us.