Skip to content

Error class hierarchy

Validation modes: Validation modes reference

Every json-tology error extends BaseError. The base class carries a machine-readable code, a human message, a retryable flag, an optional cause chain, and two structured projections (toJson(), flatten()). Every subclass adds domain-specific fields - schema IDs, JSON Pointers, validation errors.

Error constructors follow the universal DX convention: required arguments are positional in canonical order; every optional or contextual field travels in a single trailing options bag typed by an Interface or Type alias. The instance fields described below are unchanged - only the constructor argument shape collapsed into a single options object.

Never throw a bare new Error() from json-tology code. Pick the appropriate subclass.

The bookstore schemas defined in the Bookstore Domain appear in the catch examples.


BaseError

Defined in. src/errors/BaseError.ts.

Constructor. new BaseError(code, message, options?: BaseErrorOptionsType) where BaseErrorOptionsType = { cause?: Error; retryable?: boolean }. retryable defaults to false when omitted.

/**
 * BaseError constructor — the standard Error(message, options) convention.
 *
 * `message` is the required positional. `code` and all optional fields
 * (`cause`, `retryable`) travel in the required options bag.
 * `retryable` defaults to `false` when omitted from options.
 */

import { BaseError } from '../../../src/index.js';

const ioFailure = new Error('socket closed');

const bare = new BaseError('human description', { 'code': 'SOMETHING_FAILED' });
const retryable = new BaseError('human description', {
  'code': 'SOMETHING_FAILED',
  'retryable': true
});
const chained = new BaseError('human description', {
  'cause': ioFailure,
  'code': 'SOMETHING_FAILED',
  'retryable': true
});

console.assert(!bare.retryable);
console.assert(retryable.retryable);
console.assert(chained.cause === ioFailure);

console.log('bare.retryable:', bare.retryable);
console.log('retryable.retryable:', retryable.retryable);
console.log('chained.code:', chained.code);
console.log('chained.cause.message:', (chained.cause as Error).message);
Output
Press Execute to run this example against the real library.

Public surface.

MemberTypeNotes
codestringStable, machine-readable identifier
messagestringInherited from Error
retryablebooleanHint to callers about retry safety; set via options.retryable (default false)
causeError | undefinedStandard cause chain; set via options.cause
toJson()ErrorJsonInterfaceJSON-safe object including the cause chain
flatten()ErrorJsonInterface[]Root-first array of every error in the cause chain

The code values are exported as constants from src/constants/ERROR_CODES.ts for each subclass.

/**
 * BaseError — public surface: code, toJson, flatten
 *
 * Every json-tology error subclasses BaseError. Catch by class,
 * inspect the structured projections. Demonstrates the trust-boundary
 * pattern: instantiate against the canonical bookstore ReviewSchema
 * and surface the failure as a structured envelope.
 */

import { BaseError } from '../../../src/index.js';
import {
  bookstoreEntities, ReviewSchema
} from '../bookstore/index.js';

try {
  bookstoreEntities.instantiate(ReviewSchema.$id, {
    'body': 'Too',
    'rating': 99
  });
} catch (error) {
  if (error instanceof BaseError) {
    console.assert(typeof error.code === 'string');
    console.assert(typeof error.toJson() === 'object');
    console.assert(Array.isArray(error.flatten()));

    console.log('error.code:', error.code);
    console.log('error.toJson():', JSON.stringify(error.toJson(), null, 2));
    console.log('error.flatten() count:', error.flatten().length);
  }
}
Output
Press Execute to run this example against the real library.

SchemaError Runtime

Thrown for. Schema registration and structural problems - missing $id, duplicate anchors, unsupported dialect, structure validation failures.

Constructor. new SchemaError(code, message, options?: SchemaErrorOptionsType) where SchemaErrorOptionsType = { cause?: Error; schemaId?: string }.

/**
 * SchemaError constructor — the standard Error(message, options) convention.
 *
 * `message` is the required positional. `code`, `schemaId`, and `cause`
 * travel in the required options bag. The code values come from the
 * exported `SCHEMA_ERROR_CODE` map.
 */

import {
  SCHEMA_ERROR_CODE, SchemaError
} from '../../../src/index.js';

const schemaId = 'urn:bookstore:Order';
const cause = new Error('vocabulary not registered');

const missingId = new SchemaError('schema is missing $id', { 'code': SCHEMA_ERROR_CODE.MISSING_ID });
const structure = new SchemaError('invalid structure', {
  'code': SCHEMA_ERROR_CODE.STRUCTURE_INVALID,
  schemaId
});
const dialect = new SchemaError('unsupported dialect', {
  cause,
  'code': SCHEMA_ERROR_CODE.DIALECT_UNSUPPORTED,
  schemaId
});

console.assert(missingId.code === 'SCHEMA_MISSING_ID');
console.assert(structure.schemaId === schemaId);
console.assert(dialect.cause === cause);

console.log('missingId.code:', missingId.code);
console.log('structure.schemaId:', structure.schemaId);
console.log('dialect.cause.message:', dialect.cause?.message);
Output
Press Execute to run this example against the real library.

Adds. schemaId?: string (the offending schema, when known) - exposed as an instance field and set via options.schemaId.

Codes.

ConstantValueNotes
SCHEMA_ERROR_CODE.MISSING_IDSCHEMA_MISSING_ID
SCHEMA_ERROR_CODE.INVALID_INPUTSCHEMA_INVALID_INPUT
SCHEMA_ERROR_CODE.NOT_REGISTEREDSCHEMA_NOT_REGISTERED
SCHEMA_ERROR_CODE.STRUCTURE_INVALIDSCHEMA_STRUCTURE_INVALID
SCHEMA_ERROR_CODE.DUPLICATE_ANCHORSCHEMA_DUPLICATE_ANCHOR
SCHEMA_ERROR_CODE.DIALECT_UNSUPPORTEDSCHEMA_DIALECT_UNSUPPORTED
SCHEMA_ERROR_CODE.VALIDATOR_MISSINGSCHEMA_VALIDATOR_MISSING
SCHEMA_ERROR_CODE.COMPUTED_FN_MISSINGCOMPUTED_FN_MISSING
SCHEMA_ERROR_CODE.COMPUTED_INPUT_FORBIDDENCOMPUTED_INPUT_FORBIDDEN
SCHEMA_ERROR_CODE.DUPLICATE_IDSCHEMA_DUPLICATE_IDThrown by SchemaRegistry when two schemas with the same $id are registered. Detected during set() with enableDuplicateDetection enabled.
SCHEMA_ERROR_CODE.DUPLICATE_SHAPESCHEMA_DUPLICATE_SHAPEThrown by SchemaRegistry when a schema with a duplicate canonical shape (same structural hash) is registered.
SCHEMA_ERROR_CODE.PROPERTY_CHARACTERISTIC_CONFLICTPROPERTY_CHARACTERISTIC_CONFLICTThrown by SchemaRegistry when conflicting property characteristics are registered for the same property.
/**
 * SchemaError — registration / structural problems.
 *
 * A schema literal missing `$id` cannot be registered. The thrown
 * SchemaError carries the `SCHEMA_MISSING_ID` code; `schemaId` is
 * undefined because the offending schema has no identifier yet.
 */

import {
  JsonTology, SchemaError
} from '../../../src/index.js';

// invalid-input edge: a schema loaded from an untyped source (disk, network)
// arrives as `unknown` — no compile-time `$id` guarantee. Narrowing it at the
// registration boundary triggers the SCHEMA_MISSING_ID runtime guard, the
// negative path `create`'s typed signature would otherwise forbid.
const fromDisk: unknown = { 'type': 'object' };

try {
  JsonTology.create({
    'baseIri': 'https://bookstore.example',
    'schemas': [fromDisk as { readonly '$id': string }]
  });
} catch (error) {
  if (error instanceof SchemaError) {
    console.assert(error.code === 'SCHEMA_MISSING_ID');
    console.assert(error.schemaId === undefined);

    console.log('error.code:', error.code);
    console.log('error.message:', error.message);
    console.log('error.schemaId:', error.schemaId);
  }
}
Output
Press Execute to run this example against the real library.

GraphError Runtime

Thrown for. Pointer resolution failures, anchor lookup failures, ref resolution failures, dialect or vocabulary issues, recursion-limit hits.

Constructor. new GraphError(code, message, options?: GraphErrorOptionsType) where GraphErrorOptionsType = { cause?: Error; pointer?: string }.

/**
 * GraphError constructor — the standard Error(message, options) convention.
 *
 * `message` is the required positional. `code`, `pointer`, and `cause`
 * travel in the required options bag. The code values come from the
 * exported `GRAPH_ERROR_CODE` map.
 */

import {
  GRAPH_ERROR_CODE, GraphError
} from '../../../src/index.js';

const pointer = '/orderLines/0';
const cause = new Error('referenced schema absent from registry');

const notFound = new GraphError('pointer did not resolve', {
  'code': GRAPH_ERROR_CODE.POINTER_NOT_FOUND,
  'pointer': '/foo/0'
});
const refUnresolved = new GraphError('cross-schema $ref unresolved', {
  cause,
  'code': GRAPH_ERROR_CODE.REF_UNRESOLVED,
  pointer
});

console.assert(notFound.code === 'POINTER_NOT_FOUND');
console.assert(notFound.pointer === '/foo/0');
console.assert(refUnresolved.cause === cause);

console.log('notFound.code:', notFound.code);
console.log('notFound.pointer:', notFound.pointer);
console.log('refUnresolved.cause.message:', refUnresolved.cause?.message);
Output
Press Execute to run this example against the real library.

Adds. pointer?: string (the JSON Pointer involved in the failure, when applicable) - exposed as an instance field and set via options.pointer.

Codes.

ConstantValueNotes
GRAPH_ERROR_CODE.POINTER_INVALIDPOINTER_INVALID
GRAPH_ERROR_CODE.POINTER_NOT_FOUNDPOINTER_NOT_FOUND
GRAPH_ERROR_CODE.POINTER_NOT_SCHEMAPOINTER_NOT_SCHEMA
GRAPH_ERROR_CODE.ANCHOR_NOT_FOUNDANCHOR_NOT_FOUND
GRAPH_ERROR_CODE.REF_NOT_FOUNDREF_NOT_FOUND$ref ID cannot be resolved within the graph by RefResolution. Distinct from REF_UNRESOLVED: thrown when in-graph resolution fails after the schema is already loaded (pointer, anchor, and embedded-$id lookups all exhausted).
GRAPH_ERROR_CODE.REF_UNRESOLVEDREF_UNRESOLVEDCross-schema $ref points to an IRI not in the registry. Thrown on first use of a schema entry.
GRAPH_ERROR_CODE.RECURSION_LIMITRECURSION_LIMIT
GRAPH_ERROR_CODE.DIALECT_UNSUPPORTEDDIALECT_UNSUPPORTED
GRAPH_ERROR_CODE.VOCABULARY_UNSUPPORTEDVOCABULARY_UNSUPPORTED
GRAPH_ERROR_CODE.ARTIFACT_INVALIDARTIFACT_INVALID
GRAPH_ERROR_CODE.ARTIFACT_STALEARTIFACT_STALE
GRAPH_ERROR_CODE.CURSOR_CARDINALITYCURSOR_CARDINALITYThrown by Cursor and SchemaCursor when a selection that expects exactly one result contains multiple items.
GRAPH_ERROR_CODE.INVALID_LANGUAGE_TAGINVALID_LANGUAGE_TAGThrown by SchemaGraphSupport when a language tag does not conform to BCP 47 syntax.
GRAPH_ERROR_CODE.INVALID_PREDICATE_IRIINVALID_PREDICATE_IRIThrown by PredicateResolver and QuadFactory when a predicate IRI contains invalid characters or is malformed.
/**
 * GraphError — pointer resolution failure.
 *
 * `subschemaAt` walks a JSON Pointer into the canonical OrderSchema.
 * A pointer that does not address an existing fragment surfaces a
 * GraphError with code `POINTER_NOT_FOUND` and the offending pointer
 * attached.
 */

import { GraphError } from '../../../src/index.js';
import {
  bookstoreEntities, OrderSchema
} from '../bookstore/index.js';

try {
  bookstoreEntities.subschemaAt(OrderSchema.$id, '/properties/nope');
} catch (error) {
  if (error instanceof GraphError) {
    console.assert(error.code === 'POINTER_NOT_FOUND');
    console.assert(error.pointer === '/properties/nope');

    console.log('error.code:', error.code);
    console.log('error.pointer:', error.pointer);
    console.log('error.message:', error.message);
  }
}
Output
Press Execute to run this example against the real library.

InstantiationError Runtime

Thrown for. Validation failure inside instantiate() - the trust-boundary entry point. Carries the full structured error list.

Adds. errors: ValidationErrors (the full ValidationErrors collection).

Codes. Always INSTANTIATION_FAILED at the wrapper level; per-error keyword values appear inside errors.items. Additional keyword codes recorded inside errors.items:

ConstantValueWhen recorded
INSTANTIATION_ERROR_CODE.EXTRA_FORBIDDENEXTRA_FORBIDDENjt:config.extra: 'forbid' rejects unknown properties
/**
 * InstantiationError — trust-boundary failure on instantiate().
 *
 * The canonical Bastian-orders-Neverending-Story payload is fed
 * through `instantiate()` with two deliberate violations: a
 * non-positive total and a zero-quantity line item. The thrown
 * InstantiationError carries the full `ValidationErrors` collection.
 */

import { InstantiationError } from '../../../src/index.js';
import {
  bookstoreEntities, OrderSchema
} from '../bookstore/index.js';

try {
  bookstoreEntities.instantiate(OrderSchema.$id, {
    'customerId': 'c1a2b3d4-e5f6-7890-abcd-ef1234567890',
    'id': '09f8e7d6-c5b4-3210-9876-543210fedcba',
    'items': [{
      'bookIsbn': '9783522128001',
      'quantity': 0,
      'unitPrice': {
        'amount': 12.99,
        'currency': 'EUR'
      }
    }],
    'placedAt': '2026-04-12T14:23:11Z',
    'shippingAddress': {
      'city': 'München',
      'country': 'DE',
      'postalCode': '80331',
      'street': 'Reichenbachstraße 14'
    },
    'total': {
      'amount': -5,
      'currency': 'EUR'
    }
  });
} catch (error) {
  if (error instanceof InstantiationError) {
    console.assert(error.code === 'INSTANTIATION_FAILED');
    console.assert(error.errors.length > 0);

    console.log('error.code:', error.code);
    console.log('error.errors.length:', error.errors.length);
    for (const item of error.errors) {
      console.log(`  path=${item.path}  keyword=${item.keyword}  message=${item.message}`);
    }
  }
}
Output
Press Execute to run this example against the real library.

The errors collection is the same ValidationErrors used by validate() - see ValidationErrors views for the full surface.

CoercionError Runtime

Thrown for. Coercion failure, raised by value.cast(), value.convert(), and their registry equivalents (registry.cast, registry.convert) when the coerced data does not satisfy the schema. Carries the full structured error list.

Adds. errors: ValidationErrors (the full ValidationErrors collection describing every constraint that coercion could not satisfy).

Codes.

ConstantValueNotes
COERCION_ERROR_CODE.COERCION_FAILEDCOERCION_FAILEDAlways emitted at the wrapper level
/**
 * CoercionError — raised by the coercion path.
 *
 * CoercionError mirrors InstantiationError but is thrown when a
 * coercion call rejects its input. Demonstrates the public surface
 * with a deliberately-constructed instance so the catch shape is
 * exercised without depending on a private coercion site.
 */

import { CoercionError } from '../../../src/index.js';

const synthetic = new CoercionError([{
  'keyword': 'minimum',
  'message': 'must be >= 0',
  'params': {},
  'path': '/total/amount'
}], { 'code': 'COERCION_FAILED' });

if (synthetic instanceof CoercionError) {
  console.assert(synthetic.code === 'COERCION_FAILED');
  console.assert(synthetic.errors.length === 1);

  console.log('synthetic.code:', synthetic.code);
  console.log('synthetic.errors.length:', synthetic.errors.length);
  const first = synthetic.errors.items[0];

  if (first === undefined) {
    throw new Error('expected validation error');
  }
  console.log('errors[0].path:', first.path);
  console.log('errors[0].keyword:', first.keyword);
  console.log('errors[0].message:', first.message);
}
Output
Press Execute to run this example against the real library.

TransformError Runtime

Thrown for. Base class for directional transform failures. Not thrown directly by the library. See DecodeError and EncodeError.

Extends. BaseError.

Adds.

FieldTypeNotes
direction'decode' | 'encode'Which direction the transform was running when it failed
schemaIdstring | undefinedThe $id of the schema whose transform failed; filled in by the library when absent
pathstring | undefinedJSON Pointer to the field being decoded/encoded, when known

Codes.

ConstantValueSubclass
TRANSFORM_ERROR_CODE.TRANSFORM_DECODE_FAILEDTRANSFORM_DECODE_FAILEDDecodeError
TRANSFORM_ERROR_CODE.TRANSFORM_ENCODE_FAILEDTRANSFORM_ENCODE_FAILEDEncodeError

DecodeError Runtime

Thrown for. Failure inside a decode transform function, raised by jt.instantiate() when the registered decode function throws. The original throw is preserved on cause.

Extends. TransformErrorBaseError.

Constructor. new DecodeError(message: string, options?: { schemaId?, path?, cause?, retryable? }).

Fields. code === 'TRANSFORM_DECODE_FAILED', direction === 'decode', plus schemaId?, path?, cause? inherited from TransformError.

Consumer use. Custom decode handlers may throw new DecodeError('message', { path: '/field' }). The library propagates the thrown instance unchanged: message, code, path, and any other fields set by the caller are preserved. Missing schemaId context is filled in automatically.

/**
 * Transform errors — Example: DecodeError, EncodeError, CoercionError
 * Demonstrates: typed error handling for decode/encode failures and value.cast
 *
 * Three scenarios from Coreander's antiquariat:
 *   a. A decode transform rejects a malformed placement timestamp → DecodeError.
 *   b. A custom decoder throws its own DecodeError → library preserves the instance.
 *   c. An encode transform throws → EncodeError caught from jt.encode.
 *   d. value.cast on data that cannot satisfy the schema → CoercionError.
 */

import {
  CoercionError,
  DecodeError,
  EncodeError,
  Transform,
  TransformError
} from '../../../src/index.js';
import {
  BookSchema,
  createBookstoreDocRegistry
} from '../bookstore/index.js';

// createBookstoreDocRegistry seeds a permissive copy of the bookstore — docs examples extend
// it with ad-hoc demo schemas; strict-graph checking is intentionally off here.
const jt = createBookstoreDocRegistry();

// ─── a. Decode transform rejects bad input → DecodeError ────────────────────

const StrictDateSchema = Transform.create(
  {
    '$id': 'https://bookstore.example/StrictDate',
    'format': 'date-time',
    'type': 'string'
  } as const,
  {
    'decode': (raw: string) => {
      const ms = Date.parse(raw);

      if (Number.isNaN(ms)) {
        throw new TypeError(`Not a valid date string: "${raw}"`);
      }

      return new Date(ms).toISOString();
    },
    'encode': (isoString: string) => {
      return isoString;
    }
  }
);

jt.set(StrictDateSchema);

try {
  jt.instantiate(StrictDateSchema, 'not-a-date');
} catch (error) {
  if (error instanceof DecodeError) {
    console.log('a. DecodeError caught');
    console.log('   code      :', error.code);
    console.log('   direction :', error.direction);
    console.log('   cause     :', error.cause?.message);
  }
}

// ─── b. Custom decoder throws DecodeError → instance preserved ───────────────

const AnnotatedDateSchema = Transform.create(
  {
    '$id': 'https://bookstore.example/AnnotatedDate',
    'format': 'date-time',
    'type': 'string'
  } as const,
  {
    'decode': (raw: string) => {
      if (!raw.startsWith('19') && !raw.startsWith('20')) {
        throw new DecodeError('Year out of antiquariat range', {
          'code': 'TRANSFORM_DECODE_FAILED',
          'direction': 'decode',
          'path': '/placedAt'
        });
      }

      return new Date(raw).toISOString();
    },
    'encode': (isoString: string) => {
      return isoString;
    }
  }
);

jt.set(AnnotatedDateSchema);

try {
  jt.instantiate(AnnotatedDateSchema, '1800-01-01T00:00:00Z');
} catch (error) {
  if (error instanceof DecodeError) {
    console.log('b. Custom DecodeError preserved');
    console.log('   message   :', error.message);
    console.log('   path      :', error.path);
    console.log('   is TransformError:', error instanceof TransformError);
  }
}

// ─── c. Encode transform throws → EncodeError ───────────────────────────────

const GuardedEncodeSchema = Transform.create(
  {
    '$id': 'https://bookstore.example/GuardedEncode',
    'format': 'date-time',
    'type': 'string'
  } as const,
  {
    'decode': (raw: string) => {
      return new Date(raw).toISOString();
    },
    'encode': (isoString: string) => {
      const date = new Date(isoString);

      if (date.getFullYear() < 1900) {
        throw new Error('Cannot encode dates before 1900 to wire format');
      }

      return isoString;
    }
  }
);

jt.set(GuardedEncodeSchema);

const ancientDate = '1879-01-01T00:00:00Z';

try {
  jt.encode(GuardedEncodeSchema, ancientDate);
} catch (error) {
  if (error instanceof EncodeError) {
    console.log('c. EncodeError caught');
    console.log('   code      :', error.code);
    console.log('   direction :', error.direction);
    console.log('   cause     :', error.cause?.message);
  }
}

// ─── d. value.cast on uncoercible data → CoercionError ──────────────────────

// BookSchema requires 'title', 'isbn', 'authors', 'price', 'printStatus'.
// Passing an empty object fails coercion.
try {
  jt.value.cast(BookSchema.$id, {});
} catch (error) {
  if (error instanceof CoercionError) {
    console.log('d. CoercionError caught');
    console.log('   code         :', error.code);
    console.log('   errors.length:', error.errors.items.length);
  }
}
Output
Press Execute to run this example against the real library.

EncodeError Runtime

Thrown for. Failure inside an encode transform function, raised by jt.encode() (and dump) when the registered encode function throws. The original throw is preserved on cause.

Extends. TransformErrorBaseError.

Constructor. new EncodeError(message: string, options?: { schemaId?, path?, cause?, retryable? }).

Fields. code === 'TRANSFORM_ENCODE_FAILED', direction === 'encode', plus schemaId?, path?, cause? inherited from TransformError.

Consumer use. Custom encode handlers may throw new EncodeError('message'). The library propagates the thrown instance unchanged.

MaterializationError Runtime

Thrown for. Materialization failure - the result of materialize() (or ABox projection) failed validation.

Adds. schemaId: string and validationErrors: string[] (formatted path: message strings).

Codes.

ConstantValueWhen thrown
MATERIALIZATION_ERROR_CODE.MATERIALIZATION_FAILEDMATERIALIZATION_FAILEDDefault materialization failure.
MATERIALIZATION_ERROR_CODE.CYCLIC_DATACYCLIC_DATACircular reference detected during ABox projection (toQuads). Thrown by Projection when a data object contains a cycle that would loop indefinitely during RDF quad emission.
MATERIALIZATION_ERROR_CODE.INVALID_IRI_VALUEINVALID_IRI_VALUEThrown when a value that must be an IRI is not a valid IRI.
MATERIALIZATION_ERROR_CODE.NON_FINITE_NUMBERNON_FINITE_NUMBERThrown when a numeric value is Infinity or NaN, which cannot be represented in RDF.
MATERIALIZATION_ERROR_CODE.MISSING_GRAPH_IRIMISSING_GRAPH_IRIThrown when a required named-graph IRI is absent during ABox projection.
/**
 * MaterializationError — materialization failed validation.
 *
 * `materialize()` without `enablePartial` fails when the canonical
 * OrderSchema's required fields have no declared defaults — the
 * Bastian-orders fixture's required `id`, `customerId`, `items`,
 * `total`, `placedAt`, and `shippingAddress` cannot be synthesised
 * from zero-values alone.
 */

import { MaterializationError } from '../../../src/index.js';
import {
  bookstoreEntities, OrderSchema
} from '../bookstore/index.js';

try {
  bookstoreEntities.materialize(OrderSchema, {});
} catch (error) {
  if (error instanceof MaterializationError) {
    console.assert(error.code === 'MATERIALIZATION_FAILED');
    console.assert(error.schemaId === OrderSchema.$id);
    console.assert(Array.isArray(error.validationErrors));

    console.log('error.code:', error.code);
    console.log('error.schemaId:', error.schemaId);
    console.log('error.validationErrors:', error.validationErrors);
  }
}
Output
Press Execute to run this example against the real library.

Inspecting the cause chain

Every error supports flatten(), which walks the cause chain and returns a root-first array of plain objects suitable for structured logging.

/**
 * Inspecting the cause chain via `flatten()`.
 *
 * `InstantiationError.flatten()` walks the cause chain and appends
 * every item in the embedded `errors` collection. A single call
 * surfaces both the wrapper and each underlying validation issue.
 */

import { InstantiationError } from '../../../src/index.js';
import {
  bookstoreEntities, ReviewSchema
} from '../bookstore/index.js';

try {
  bookstoreEntities.instantiate(ReviewSchema.$id, {
    'body': 'no',
    'rating': 12
  });
} catch (error) {
  if (error instanceof InstantiationError) {
    const entries = error.flatten();

    console.assert(entries.length > 0);

    console.log('flatten() entry count:', entries.length);
    for (const entry of entries) {
      console.log(`  code=${entry.code}  retryable=${entry.retryable}  message=${entry.message}`);
    }
  }
}
Output
Press Execute to run this example against the real library.

InstantiationError.flatten() and CoercionError.flatten() additionally append every item in their errors collection, so a single call surfaces both the wrapper and each underlying validation issue.

See also

Released under the MIT License.