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

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:

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:

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:

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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →