or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

error-handling.mdindex.mdmessages.mdrules.mdschema.mdvalidation-types.md
tile.json

error-handling.mddocs/

Error Handling

Comprehensive error reporting with field-specific errors, custom messages, and structured error objects.

Capabilities

Error Types

Core error interfaces and types for validation results.

interface ValidateError {
  message?: string;
  fieldValue?: Value;
  field?: string;
}

type ValidateFieldsError = Record<string, ValidateError[]>;

type ValidateCallback = (
  errors: ValidateError[] | null,
  fields: ValidateFieldsError | Values
) => void;

type SyncErrorType = Error | string;

Validation Error Object

Individual validation error containing details about what failed.

interface ValidateError {
  /** Error message describing what validation failed */
  message?: string;
  /** The actual value that failed validation */
  fieldValue?: Value;
  /** The field name that failed validation */
  field?: string;
}

Usage Example:

const schema = new Schema({
  name: { type: "string", required: true, min: 2 }
});

try {
  await schema.validate({ name: "A" });
} catch (error) {
  console.log(error.errors[0]);
  // Output: {
  //   message: "name must be at least 2 characters",
  //   fieldValue: "A",
  //   field: "name"
  // }
}

Field-Specific Errors

Organized error mapping for easy field-level error handling.

type ValidateFieldsError = Record<string, ValidateError[]>;

Usage Example:

const schema = new Schema({
  name: { type: "string", required: true },
  email: { type: "email", required: true },
  age: { type: "number", min: 0 }
});

try {
  await schema.validate({
    name: "",
    email: "invalid-email",
    age: -5
  });
} catch (error) {
  console.log(error.fields);
  // Output: {
  //   name: [{ message: "name is required", field: "name", fieldValue: "" }],
  //   email: [{ message: "email is not a valid email", field: "email", fieldValue: "invalid-email" }],
  //   age: [{ message: "age cannot be less than 0", field: "age", fieldValue: -5 }]
  // }
  
  // Access specific field errors
  const nameErrors = error.fields.name;
  const emailErrors = error.fields.email;
}

Callback-Based Error Handling

Traditional callback pattern for handling validation results.

type ValidateCallback = (
  errors: ValidateError[] | null,
  fields: ValidateFieldsError | Values
) => void;

Usage Examples:

// Success case
schema.validate(validData, (errors, fields) => {
  if (errors) {
    // Validation failed
    console.log("Validation errors:", errors);
    console.log("Field errors:", fields);
  } else {
    // Validation passed - fields contains validated data
    console.log("Validation passed:", fields);
  }
});

// Error case
schema.validate(invalidData, (errors, fields) => {
  if (errors) {
    // Handle each error
    errors.forEach(error => {
      console.log(`Field ${error.field}: ${error.message}`);
    });
    
    // Handle field-specific errors
    Object.keys(fields).forEach(fieldName => {
      const fieldErrors = fields[fieldName];
      console.log(`${fieldName} has ${fieldErrors.length} errors`);
    });
  }
});

Promise-Based Error Handling

Modern promise/async-await pattern with structured error objects.

Usage Examples:

// Promise with .catch()
schema.validate(data)
  .then(validatedData => {
    console.log("Success:", validatedData);
  })
  .catch(error => {
    console.log("Validation failed");
    console.log("Errors:", error.errors);
    console.log("Fields:", error.fields);
  });

// Async/await with try-catch
try {
  const result = await schema.validate(data);
  console.log("Validation passed:", result);
} catch (error) {
  // error is an AsyncValidationError instance
  console.log("Validation failed");
  
  // Array of all errors
  error.errors.forEach(err => {
    console.log(`${err.field}: ${err.message}`);
  });
  
  // Field-organized errors
  Object.entries(error.fields).forEach(([field, errors]) => {
    console.log(`${field} has ${errors.length} error(s)`);
  });
}

AsyncValidationError Class

Structured error class thrown by promise-based validation.

class AsyncValidationError extends Error {
  errors: ValidateError[];
  fields: Record<string, ValidateError[]>;
  
  constructor(
    errors: ValidateError[],
    fields: Record<string, ValidateError[]>
  );
}

Usage Example:

try {
  await schema.validate(invalidData);
} catch (error) {
  if (error instanceof AsyncValidationError) {
    console.log("Async validation error occurred");
    console.log(`Total errors: ${error.errors.length}`);
    console.log(`Fields with errors: ${Object.keys(error.fields).length}`);
  }
}

Error Control Options

Configure error handling behavior through validation options.

interface ValidateOption {
  suppressWarning?: boolean;
  suppressValidatorError?: boolean;
  first?: boolean;
  firstFields?: boolean | string[];
  error?: (rule: InternalRuleItem, message: string) => ValidateError;
}

Suppress Warnings

Control warning output during validation.

suppressWarning?: boolean;

Usage Example:

// Suppress console warnings
await schema.validate(data, { suppressWarning: true });

Suppress Validator Errors

Control error throwing in custom validators.

suppressValidatorError?: boolean;

Usage Example:

await schema.validate(data, { suppressValidatorError: true });

First Error Only

Stop validation on the first error encountered.

first?: boolean;

Usage Example:

try {
  await schema.validate(data, { first: true });
} catch (error) {
  // Only contains the first error found
  console.log(`First error: ${error.errors[0].message}`);
}

First Field Errors

Stop validation on first error per field or specified fields.

firstFields?: boolean | string[];

Usage Examples:

// Stop on first error for all fields
await schema.validate(data, { firstFields: true });

// Stop on first error for specific fields only
await schema.validate(data, { 
  firstFields: ["username", "email"] 
});

Custom Error Factory

Provide custom error object creation function.

error?: (rule: InternalRuleItem, message: string) => ValidateError;

Usage Example:

await schema.validate(data, {
  error: (rule, message) => ({
    message: `Validation failed: ${message}`,
    field: rule.field,
    fieldValue: rule.value,
    timestamp: new Date().toISOString(),
    ruleType: rule.type
  })
});

Error Message Patterns

Common patterns for handling different error scenarios.

Field-Level Error Display

const displayFieldErrors = (fields) => {
  Object.entries(fields).forEach(([fieldName, errors]) => {
    const errorMessages = errors.map(err => err.message);
    console.log(`${fieldName}: ${errorMessages.join(', ')}`);
  });
};

try {
  await schema.validate(data);
} catch (error) {
  displayFieldErrors(error.fields);
}

Error Aggregation

const aggregateErrors = (errors) => {
  const summary = {
    total: errors.length,
    byField: {},
    byType: {}
  };
  
  errors.forEach(error => {
    // Group by field
    if (!summary.byField[error.field]) {
      summary.byField[error.field] = [];
    }
    summary.byField[error.field].push(error.message);
  });
  
  return summary;
};

try {
  await schema.validate(data);
} catch (error) {
  const summary = aggregateErrors(error.errors);
  console.log(`Total errors: ${summary.total}`);
}

Conditional Error Handling

const handleErrors = (error) => {
  if (error.errors.length === 1) {
    // Single error - show inline
    const err = error.errors[0];
    showInlineError(err.field, err.message);
  } else {
    // Multiple errors - show summary
    showErrorSummary(error.fields);
  }
};

try {
  await schema.validate(data);
} catch (error) {
  handleErrors(error);
}

Nested Object Error Handling

Handle errors in nested object validation.

Usage Example:

const schema = new Schema({
  user: {
    type: "object",
    fields: {
      profile: {
        type: "object",
        fields: {
          name: { type: "string", required: true },
          age: { type: "number", min: 0 }
        }
      }
    }
  }
});

try {
  await schema.validate({
    user: {
      profile: {
        name: "",
        age: -5
      }
    }
  });
} catch (error) {
  // Nested field errors use dot notation
  console.log(error.fields);
  // Output: {
  //   "user.profile.name": [{ message: "user.profile.name is required", ... }],
  //   "user.profile.age": [{ message: "user.profile.age cannot be less than 0", ... }]
  // }
}