VizForDocs
The language

What gets refused

Every rejection code, the reserved attributes no Block declares, the budgets a document lives inside, and why refusals are structured.

A rejection names a code, the element and the parameter at fault, and — where the shape of the mistake makes it knowable — a suggestion. That is deliberate: a caller that knows what was wrong repairs the named thing, while a caller handed a paragraph tries a different shape of the same call.

Validation is accumulating. The whole list of issues comes back at once, so a document can be repaired in one pass rather than one issue per attempt.

The codes

CodeWhat it means
parse-errorMalformed markup at the tokenizer level: bad attribute syntax, a stray `<`, end of input inside a tag.
malformed-markupStructurally malformed: an unclosed element, a stray end tag, mismatched nesting.
forbidden-syntaxSyntax the format forbids outright: comments, doctype, CDATA, processing instructions, self-closing tags.
unknown-elementA `vf-*` element with no Block registered for it. The vocabulary is closed.
foreign-elementA non-`vf-*` element — `<script>`, `<div>`, `<img>`. Only Blocks may appear.
unknown-attributeAn attribute the Block's schema does not declare.
forbidden-attributeAn attribute the format bans by name: `style`, `class`, `id`, `on*`, `data-*`.
invalid-paramAn attribute value the Block's schema rejects.
content-modelChildren or text where the Block's content model forbids them.
structureA document-shape rule: the root, a required or unique child, an allowed parent.
forbidden-uriA parameter carrying an `http`, `file`, `data`, `blob` or `javascript` URI. Material is referenced as `asset://`.
duplicate-idTwo nodes carrying the same `vf-id`.
invalid-idA `vf-id` that is not a legal id.
limit-exceededNode count, nesting depth or source size over budget.
unsupported-versionThe document declares a format version this build cannot read or migrate from.

Reserved attributes

Four attributes are handled outside every Block schema, so no Block declares them and no Block can:

AttributeWhat it holds
vf-idThe node's identity. Minted at parse for anything that did not write one.
vf-nameA readable layer name, up to 64 characters.
vf-lockedA decision that this node and everything inside it is not to be changed.
vf-hiddenNot drawn, but still present, still parameterised, still in paint order.

Because they are not parameters, block.setParam structurally cannot reach them: locking has its own command (node.setLocked), with its own entry in the history. That is the point — unlocking something is somebody overriding a decision, and it should read that way in the record rather than looking like an ordinary attribute write.

A locked node refuses every command except node.setLocked, and so does everything inside it: deleting an unlocked parent that holds a locked child is refused. Locking a group locks its contents, and a reading of the document reports the lock resolved — so an agent sees a lock rather than meeting one.

Undo is deliberately outside the guard. Undo restores a state that was legitimate when it existed, and a guard there would make history un-replayable.

What is forbidden outright

  • Comments. <!-- … --> is refused, and so are doctype, CDATA and processing instructions. A document is Blocks and nothing else. Reasoning about the design goes in <vf-brief>, which travels with it; a note about one node goes in vf-name.
  • Foreign elements. <div>, <img>, <script> — anything that is not a registered vf-* Block.
  • The escape hatches. style, class, id, on* and data-* attributes are refused by name. There is no way to write CSS into a document, which is what makes the render predictable enough to check.
  • Self-closing tags. Write <vf-background …></vf-background>.

Budgets

A document may hold at most 5000 nodes and nest at most 32 levels deep; over either, validation fails with limit-exceeded rather than the renderer discovering it later. A render call is bounded in turn, by emitted nodes and by wall clock, so a Block cannot loop the renderer.

The gate is separate from this

Validation says whether a document is legal. The Channel Checks say whether it is deliverable, and they are a separate pass with their own version stamp. Two of them fail a frame — a character no bundled face can draw, and an asset:// that resolves to nothing, both of which mean the rendered file is broken rather than that the design is wrong. The rest report and block nothing: contrast, the safe area, a synthesized italic, clipped content, overlapping type.

The rules that gate a design →

On this page