---
title: Validation
description: validate() returns errors for structural problems and warnings for things that render fine and are probably still wrong.
status: shipped
url: https://getairframe.com/framewerk/core/validation
---

> Part of the Framewerk docs. Index of every page: /framewerk/llms.txt

# Validation

`validate()` returns `{ valid, errors, warnings }`: **errors** are things the renderer cannot make sense of, **warnings** are things that render fine and are probably still wrong.

## Examples

Validating a good spec:

**A spec that validates clean**

```json
{
  "formatVersion": "1.0",
  "screens": [
    {
      "id": "home",
      "layout": {
        "_id": "root",
        "type": "column",
        "gap": 12,
        "padding": 16,
        "children": [
          { "_id": "h", "type": "text", "variant": "heading", "content": "Hello" },
          { "_id": "go", "type": "button", "content": "Order", "action": "navigate(order)" }
        ]
      }
    },
    {
      "id": "order",
      "layout": { "_id": "order-root", "type": "text", "content": "Order" }
    }
  ]
}
```

The same shape with a dangling navigate — structurally valid, warning on the button:

**A dangling navigate warns**

```json
{
  "formatVersion": "1.0",
  "screens": [
    {
      "id": "home",
      "layout": {
        "_id": "root",
        "type": "column",
        "gap": 12,
        "padding": 16,
        "children": [
          { "_id": "h", "type": "text", "variant": "heading", "content": "Hello" },
          { "_id": "go", "type": "button", "content": "Order", "action": "navigate(nope)" }
        ]
      }
    }
  ]
}
```

## Anatomy

```ts
import { validate } from "@framewerk/spec";

const result = validate(spec);
result.valid;     // boolean
result.errors;    // structural problems — the spec is wrong
result.warnings;  // suspicious but renderable
```

**Errors** are things the renderer cannot make sense of: an unknown node type, a malformed layout tree, an invalid enum value (`"variant": "zzz"` on a button).

**Warnings** are things that render fine and are probably still wrong:

```
navigate(nope) targets an unknown screen "nope"
Unrecognized action "frobnicate(9)" — expected navigate(screenId), back(),
  setState(key, value), toggleState(key), scrollTo(anchor), or openUrl(address)
Screen "home" has an empty layout with no children
```

Note where the line falls. A dangling `navigate()` and an unparseable action are **warnings, not errors** — the spec is structurally valid and the screen draws correctly; the button just does nothing when clicked. That is the most expensive class of bug in a wireframe and the easiest to miss by eye, so **treat warnings as failures in CI** unless you have a specific reason not to. `validate()` reports them; it does not rank them for you.

The package also exports the pieces the validator is built from — `parseAction`, `evaluateExpression`, `normalizeLayoutTree`, `resolveId`, `lintActionStrings`, `collectReachableScreenIds` — so you can build your own tooling on the format without reimplementing its semantics. See the [API reference](../api-reference.md).

## Stability

The format versions with `@framewerk/spec` under semver. A change that invalidates a previously-valid document is breaking, even when the TypeScript surface is untouched. The checked-in `api-report.md` in each package is the machine-checked record of the exported surface.

Adding a node type or an optional prop is additive. Removing one, or narrowing what an existing field accepts, is not.
