# How Archify's Validator Provides Actionable Hints with ID/Label Context

> Archify's validator transforms cryptic JSON pointers into actionable hints by adding ID or label context. Understand validation errors faster and improve your data quality.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Archify enriches JSON Schema validation errors by walking the `instancePath` and appending the nearest element's `id` or `label`, turning cryptic JSON pointers like `/nodes/3/label` into clear, actionable references such as `/nodes/3 (id/label: "router") /label must be a string`.**

Archify validates diagram JSON against auto-generated AJV validators to ensure structural integrity. When validation fails, the system does not return raw schema errors; instead, it processes each failure through a context-aware formatter that injects human-readable identifiers. According to the tt-a1i/archify source code, this enrichment happens in `archify/renderers/shared/validator.mjs`, where the validator dereferences the error path and extracts meaningful labels from the actual data nodes.

## The Validation Pipeline and Generated Validators

Archify uses **AJV** (Another JSON Schema Validator) to validate diagrams against strict schemas. The validators themselves are auto-generated and live in `archify/renderers/shared/generated-validators.mjs`, created by the build script at `archify/scripts/generate-validators.mjs`. When `validateSchema()` encounters a mismatch, AJV returns an array of error objects containing `instancePath` (the JSON pointer) and `message` (the constraint violation).

However, knowing that an error occurred at `/nodes/3/properties/label` requires manual lookup to identify which diagram element failed. The validator solves this by passing both the error metadata and the original data object to a helper function that reconstructs the path with context.

## Walking the Instance Path with `annotatePath`

The core enrichment logic resides in the `annotatePath` function inside `archify/renderers/shared/validator.mjs`. This utility accepts the AJV `instancePath` and the full data object, then walks the path segment-by-segment to locate the offending node:

```javascript
function annotatePath(instancePath, data) {
  if (!instancePath) return '/';
  let node = data;
  let hint = null;
  for (const seg of instancePath.split('/').slice(1)) {
    if (node == null || typeof node !== 'object') break;
    node = node[/^\d+$/.test(seg) ? Number(seg) : seg];
    if (node && typeof node === 'object' && !Array.isArray(node)) {
      const tag = node.id ?? node.label;   // ← picks id or label
      if (tag != null) hint = String(tag);
    }
  }
  return hint != null
    ? `${instancePath} (id/label: ${JSON.stringify(hint)})`
    : instancePath;
}

```

The function iterates through each path segment, dereferencing arrays by index and objects by key. At every step, it checks if the current node possesses an **`id`** or **`label`** property. If found, it stores that value as the `hint`. Once the traversal completes, it returns either the original path (if no identifier was found) or the path annotated with the discovered context.

## Formatting Context-Rich Error Messages

After `annotatePath` resolves the human-readable hint, `formatErrors` assembles the final output. The formatter constructs a multi-line error message where each line contains the annotated path, the original AJV message, and any additional schema details:

```javascript
return `  ${where} ${e.message}${detail}`;

```

This produces diagnostic output where developers can immediately identify the problematic element by name or ID rather than array index. For example, instead of receiving a generic pointer, you see the exact node reference:

```

/nodes/3 (id/label: "router") /label must be a string

```

## Running Validation in Your Code

You can leverage this validation logic programmatically to catch schema violations before rendering diagrams. The validator throws enriched errors that include the ID/label context for every failure:

```javascript
import { validateSchema } from './renderers/shared/validator.mjs';
import workflowJson from './examples/web-app.architecture.json' assert { type: 'json' };

try {
  // Throws with enriched hints if JSON violates the schema
  validateSchema('workflow', workflowJson);
  console.log('✅ Workflow diagram is valid');
} catch (err) {
  console.error('❌ Validation error:\n' + err.message);
}

```

If **node 3** in your workflow contains an invalid label, the caught error displays the contextual hint automatically:

```

❌ Validation error:
workflow schema validation failed:
  /nodes/3 (id/label: "router") /label must be a string

```

## Key Implementation Files

The validation system spans several modules that work together to provide actionable hints:

- `archify/renderers/shared/validator.mjs` – Core validation logic with `annotatePath` and `formatErrors`
- `archify/renderers/shared/generated-validators.mjs` – Auto-generated AJV validators for each diagram type
- `archify/scripts/generate-validators.mjs` – Build script that generates the standalone validator module
- `archify/test/layout-rules.test.mjs` – Test suite verifying hint format and validation coverage

## Summary

- **AJV validation errors** in Archify contain machine-friendly JSON pointers that obscure which diagram element failed.
- The **`annotatePath`** function in `archify/renderers/shared/validator.mjs` walks the error path and extracts the nearest `id` or `label` from the data object.
- Error messages are formatted to include the enriched context, allowing developers to identify elements by human-readable names rather than array indices.
- The validation pipeline supports programmatic usage via `validateSchema()`, throwing detailed errors that reference specific diagram nodes.

## Frequently Asked Questions

### How does Archify determine which ID or label to display in validation errors?

The `annotatePath` function traverses the error path segment-by-segment and inspects each node for an **`id`** or **`label`** property using the nullish coalescing operator (`node.id ?? node.label`). It captures the first valid identifier encountered during the walk and appends it to the error path as context.

### What file contains the core logic for enriching validation errors with context?

The enrichment logic lives in `archify/renderers/shared/validator.mjs`. This module exports `validateSchema` and contains the internal `annotatePath` helper that dereferences JSON pointers against the supplied data object to extract identifiers.

### How does the validator handle cases where no ID or label exists?

If `annotatePath` traverses the entire `instancePath` without finding an **`id`** or **`label`** property, the function returns the original JSON pointer unchanged. The error message will show the raw path (e.g., `/edges/5/type`) without the `(id/label: ...)` annotation.

### Can I use the validator programmatically in my own Node.js scripts?

Yes. You can import `validateSchema` from `archify/renderers/shared/validator.mjs` and invoke it with a diagram type string (such as `'workflow'`) and a data object. The function throws a detailed error string containing formatted, context-rich messages if validation fails, making it suitable for CI/CD pipelines and pre-commit hooks.