CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-z-schema

JSON schema validator for JavaScript with comprehensive validation capabilities and support for both synchronous and asynchronous validation modes

Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error reporting system with detailed validation failure information and customizable error handling. z-schema provides rich error information to help debug validation failures and implement custom error handling logic.

Capabilities

Get Last Error

Retrieve the most recent validation error as a structured Error object.

/**
 * Get the most recent validation error
 * @returns Error object with validation details or null if validation succeeded
 */
getLastError(): ZSchema.SchemaError | null;

Usage Examples:

const ZSchema = require("z-schema");
const validator = new ZSchema();

const schema = {
    type: "object",
    properties: {
        name: { type: "string", minLength: 5 },
        age: { type: "number", minimum: 18 }
    },
    required: ["name", "age"]
};

const data = { name: "Jo", age: 16 };
const valid = validator.validate(data, schema);

if (!valid) {
    const error = validator.getLastError();
    console.log("Error name:", error.name); 
    // Output: "z-schema validation error"
    
    console.log("Error message:", error.message);
    // Output: Summary message about validation failure
    
    console.log("Error details:", error.details);
    // Output: Array of detailed error information
    
    // Use as standard Error object
    throw error;
}

Get Last Errors

Retrieve detailed array of all validation errors from the most recent validation.

/**
 * Get array of all validation errors from last validation
 * @returns Array of error details or null if validation succeeded
 */
getLastErrors(): ZSchema.SchemaErrorDetail[] | null;

Usage Examples:

const validator = new ZSchema();

const schema = {
    type: "object",
    properties: {
        email: { type: "string", format: "email" },
        age: { type: "number", minimum: 0, maximum: 120 },
        tags: { 
            type: "array", 
            items: { type: "string" },
            minItems: 1
        }
    },
    required: ["email", "age"]
};

const invalidData = {
    email: "not-an-email",
    age: -5,
    tags: []
};

const valid = validator.validate(invalidData, schema);

if (!valid) {
    const errors = validator.getLastErrors();
    
    errors.forEach((error, index) => {
        console.log(`Error ${index + 1}:`);
        console.log(`  Code: ${error.code}`);
        console.log(`  Message: ${error.message}`);
        console.log(`  Path: ${error.path}`);
        console.log(`  Params:`, error.params);
        
        if (error.inner && error.inner.length > 0) {
            console.log(`  Inner errors:`, error.inner.length);
        }
    });
    
    /* Example output:
    Error 1:
      Code: INVALID_FORMAT
      Message: Object didn't pass validation for format email: not-an-email
      Path: #/email
      Params: ["email", "not-an-email"]
    
    Error 2:
      Code: MINIMUM
      Message: Value -5 is less than minimum 0
      Path: #/age
      Params: ["-5", "0"]
    
    Error 3:
      Code: ARRAY_LENGTH_SHORT
      Message: Array is too short (0), minimum 1
      Path: #/tags
      Params: ["0", "1"]
    */
}

Custom Error Handling

Implement custom error handling with detailed error analysis.

// Error analysis helper functions
function analyzeValidationErrors(errors) {
    const errorsByType = {};
    const errorsByPath = {};
    
    errors.forEach(error => {
        // Group by error type
        if (!errorsByType[error.code]) {
            errorsByType[error.code] = [];
        }
        errorsByType[error.code].push(error);
        
        // Group by path
        if (!errorsByPath[error.path]) {
            errorsByPath[error.path] = [];
        }
        errorsByPath[error.path].push(error);
    });
    
    return { errorsByType, errorsByPath };
}

Usage Examples:

const validator = new ZSchema();

function validateWithCustomErrorHandling(data, schema) {
    const valid = validator.validate(data, schema);
    
    if (!valid) {
        const errors = validator.getLastErrors();
        const { errorsByType, errorsByPath } = analyzeValidationErrors(errors);
        
        // Handle specific error types
        if (errorsByType.INVALID_TYPE) {
            console.log("Type validation errors found:");
            errorsByType.INVALID_TYPE.forEach(error => {
                console.log(`  ${error.path}: expected ${error.params[0]}, got ${error.params[1]}`);
            });
        }
        
        if (errorsByType.INVALID_FORMAT) {
            console.log("Format validation errors found:");
            errorsByType.INVALID_FORMAT.forEach(error => {
                console.log(`  ${error.path}: invalid ${error.params[0]} format`);
            });
        }
        
        // Handle errors by field
        Object.keys(errorsByPath).forEach(path => {
            const fieldErrors = errorsByPath[path];
            console.log(`Field ${path} has ${fieldErrors.length} error(s)`);
        });
        
        return {
            valid: false,
            errors: errors,
            summary: {
                totalErrors: errors.length,
                errorTypes: Object.keys(errorsByType),
                affectedFields: Object.keys(errorsByPath)
            }
        };
    }
    
    return { valid: true, errors: null, summary: null };
}

// Usage
const result = validateWithCustomErrorHandling(data, schema);
if (!result.valid) {
    console.log("Validation summary:", result.summary);
}

Custom Validator Function

Implement custom validation logic with error reporting.

/**
 * Custom validator function interface
 * @param report - Report object for adding custom errors
 * @param schema - Current schema being validated
 * @param json - Current JSON data being validated
 */
interface CustomValidatorFunction {
    (report: Report, schema: any, json: any): void;
}

interface Report {
    /**
     * Add custom error to validation report
     * @param errorCode - Custom error code
     * @param errorMessage - Error message template with {0}, {1} placeholders
     * @param params - Array of parameters for message template
     * @param subReports - Sub-schema reports (optional)
     * @param schemaDescription - Schema description (optional)
     */
    addCustomError(
        errorCode: string,
        errorMessage: string, 
        params: string[],
        subReports?: any,
        schemaDescription?: string
    ): void;
}

Usage Examples:

// Custom validator for business logic
function businessRulesValidator(report, schema, json) {
    // Custom validation: ensure unique properties
    if (Array.isArray(schema.uniqueProperties)) {
        const seenValues = [];
        
        schema.uniqueProperties.forEach(prop => {
            const value = json[prop];
            if (typeof value !== "undefined") {
                if (seenValues.indexOf(value) !== -1) {
                    report.addCustomError(
                        "NON_UNIQUE_PROPERTY_VALUE",
                        "Property '{0}' has non-unique value: {1}",
                        [prop, value.toString()],
                        null,
                        schema.description
                    );
                }
                seenValues.push(value);
            }
        });
    }
    
    // Custom validation: business date rules
    if (schema.businessDateValidation && json.startDate && json.endDate) {
        const start = new Date(json.startDate);
        const end = new Date(json.endDate);
        
        if (start >= end) {
            report.addCustomError(
                "INVALID_DATE_RANGE",
                "Start date '{0}' must be before end date '{1}'",
                [json.startDate, json.endDate],
                null,
                "Business rule: start date must precede end date"
            );
        }
        
        const maxDuration = 365 * 24 * 60 * 60 * 1000; // 1 year in ms
        if (end - start > maxDuration) {
            report.addCustomError(
                "DATE_RANGE_TOO_LONG",
                "Date range cannot exceed 1 year: {0} to {1}",
                [json.startDate, json.endDate]
            );
        }
    }
}

// Use custom validator
const validator = new ZSchema({
    customValidator: businessRulesValidator
});

const schema = {
    type: "object",
    properties: {
        fromAccount: { type: "string" },
        toAccount: { type: "string" },
        startDate: { type: "string", format: "date" },
        endDate: { type: "string", format: "date" }
    },
    uniqueProperties: ["fromAccount", "toAccount"],
    businessDateValidation: true
};

// This will trigger custom validation errors
const invalidData = {
    fromAccount: "12345",
    toAccount: "12345", // Same as fromAccount - will trigger uniqueness error
    startDate: "2023-12-01",
    endDate: "2023-06-01" // Before startDate - will trigger date range error
};

const valid = validator.validate(invalidData, schema);
if (!valid) {
    const errors = validator.getLastErrors();
    errors.forEach(error => {
        if (error.code.startsWith("NON_UNIQUE") || error.code.startsWith("INVALID_DATE")) {
            console.log("Custom validation error:", error.message);
        }
    });
}

Error Structure and Types

Error Object Structure

interface SchemaError extends Error {
    /** Always "z-schema validation error" */
    name: string;
    
    /** Summary error message */
    message: string;
    
    /** Detailed error information array */
    details: SchemaErrorDetail[];
}

interface SchemaErrorDetail {
    /** Descriptive error message */
    message: string;
    
    /** Error code identifier */
    code: string;
    
    /** Parameters used in error message */
    params: string[];
    
    /** JSON path to the error location */
    path: string;
    
    /** Schema description (if available) */
    description: string;
    
    /** Nested errors for complex validation failures */
    inner: SchemaErrorDetail[];
}

Common Error Codes

// Type validation errors
interface TypeErrors {
    "INVALID_TYPE": "Expected type {0} but found type {1}";
    "INVALID_FORMAT": "Object didn't pass validation for format {0}: {1}";
    "ENUM_MISMATCH": "No enum match for: {0}";
    "ENUM_CASE_MISMATCH": "Enum does not match case for: {0}";
}

// Composition validation errors  
interface CompositionErrors {
    "ANY_OF_MISSING": "Data does not match any schemas from 'anyOf'";
    "ONE_OF_MISSING": "Data does not match any schemas from 'oneOf'";
    "ONE_OF_MULTIPLE": "Data is valid against more than one schema from 'oneOf'";
    "NOT_PASSED": "Data matches schema from 'not'";
}

// Array validation errors
interface ArrayErrors {
    "ARRAY_LENGTH_SHORT": "Array is too short ({0}), minimum {1}";
    "ARRAY_LENGTH_LONG": "Array is too long ({0}), maximum {1}";
    "ARRAY_UNIQUE": "Array items are not unique (indexes {0} and {1})";
    "ARRAY_ADDITIONAL_ITEMS": "Additional items not allowed";
}

// Numeric validation errors
interface NumericErrors {
    "MULTIPLE_OF": "Value {0} is not a multiple of {1}";
    "MINIMUM": "Value {0} is less than minimum {1}";
    "MINIMUM_EXCLUSIVE": "Value {0} is equal or less than exclusive minimum {1}";
    "MAXIMUM": "Value {0} is greater than maximum {1}";
    "MAXIMUM_EXCLUSIVE": "Value {0} is equal or greater than exclusive maximum {1}";
}

// Object validation errors
interface ObjectErrors {
    "OBJECT_PROPERTIES_MINIMUM": "Too few properties defined ({0}), minimum {1}";
    "OBJECT_PROPERTIES_MAXIMUM": "Too many properties defined ({0}), maximum {1}";
    "OBJECT_MISSING_REQUIRED_PROPERTY": "Missing required property: {0}";
    "OBJECT_ADDITIONAL_PROPERTIES": "Additional properties not allowed: {0}";
    "OBJECT_DEPENDENCY_KEY": "Dependency failed - key must exist: {0} (due to key: {1})";
}

// String validation errors
interface StringErrors {
    "MIN_LENGTH": "String is too short ({0} chars), minimum {1}";
    "MAX_LENGTH": "String is too long ({0} chars), maximum {1}";
    "PATTERN": "String does not match pattern {0}: {1}";
}

// Schema and reference errors
interface SchemaErrors {
    "UNRESOLVABLE_REFERENCE": "Reference could not be resolved: {0}";
    "UNKNOWN_FORMAT": "There is no validation function for format '{0}'";
    "ASYNC_TIMEOUT": "{0} asynchronous task(s) have timed out after {1} ms";
}

Error Reporting Configuration

Error Path Formatting

Control how error paths are reported in validation results.

interface ErrorReportingOptions {
    /** Report error paths as arrays instead of strings (default: false) */
    reportPathAsArray?: boolean;
    
    /** Stop after first error instead of collecting all errors (default: false) */
    breakOnFirstError?: boolean;
}

Usage Examples:

// String paths (default)
const validator1 = new ZSchema();
validator1.validate({ user: { name: 123 } }, schema);
const errors1 = validator1.getLastErrors();
console.log(errors1[0].path); // "#/user/name"

// Array paths
const validator2 = new ZSchema({ reportPathAsArray: true });
validator2.validate({ user: { name: 123 } }, schema);
const errors2 = validator2.getLastErrors();
console.log(errors2[0].path); // ["user", "name"]

// Fast-fail validation
const validator3 = new ZSchema({ breakOnFirstError: true });
validator3.validate(invalidData, schema);
const errors3 = validator3.getLastErrors();
console.log(errors3.length); // 1 (only first error)

Selective Error Reporting

Validate only specific error types for performance optimization.

interface SelectiveValidationOptions {
    /** Only check for specific error types during validation */
    includeErrors?: string[];
}

Usage Examples:

const validator = new ZSchema();

// Only check for type errors
const valid = validator.validate(data, schema, {
    includeErrors: ["INVALID_TYPE"]
});

// Only check for format and length errors
const valid2 = validator.validate(data, schema, {
    includeErrors: ["INVALID_FORMAT", "MIN_LENGTH", "MAX_LENGTH"]
});

// Performance benefit: skips other validation checks
const valid3 = validator.validate(data, schema, {
    includeErrors: ["OBJECT_MISSING_REQUIRED_PROPERTY"]
});

Install with Tessl CLI

npx tessl i tessl/npm-z-schema

docs

error-handling.md

format-validation.md

index.md

schema-management.md

validation.md

tile.json