Validation rules
A producer of ChatMapper JSON should implement at least the errors below; they are cheap and they catch hand-edited files. The warnings are content advice the editor shows writers. Each rule is stated as the validator reports it.
Errors
Section titled “Errors”A document with any of these is malformed or will not play as written.
| Rule | Scope |
|---|---|
Missing Assets | The top-level Assets object is absent. |
<Collection>: duplicate ID n | Two entries in Actors, Items, Locations, UserVariables or Conversations share an ID. |
No actors defined / No conversations defined | The collection is empty. |
duplicate node ID n | Two nodes in one conversation share an ID. |
conversation has no dialog nodes | DialogNodes is empty. |
no root node / multiple root nodes (…) | Exactly one node per conversation must have IsRoot: true. |
node ConversationID x != conversation y | A node’s ConversationID does not match its container. |
bad Actor reference "…" / bad Conversant reference "…" | The value is not "", "-1", or an existing actor ID. |
condition references undefined variable "…" | Variable["name"] in a ConditionsString names a variable not in UserVariables (by Name, or by cleaned Lua name). |
link OriginConvoID mismatch / link OriginDialogID mismatch | A link’s origin fields do not match the node it sits on. |
link to missing conversation n | DestinationConvoID names no conversation. |
link to missing node n (optionally in conversation m) | DestinationDialogID names no node in the destination conversation. |
Warnings
Section titled “Warnings”| Rule | Scope |
|---|---|
No player actor (IsPlayer=True) | No actor is flagged as the player. Some exports need one. |
script references undefined variable "…" | A UserScript sets a variable never declared. Works at runtime; declare it so its initial value is defined. |
duplicate link to c:n | The same destination is linked twice from one node. |
node has no dialogue or menu text | A non-root, non-group node with both text fields empty. |
dialogue line has no actor (speaker) | A node with Dialogue Text but no Actor, unless its Menu Text carries [a] (an action line plays under a synthetic speaker). Desktop treats this as an error; the web validator warns. |
unreachable node | No path from the root reaches it following links within the conversation. |
node has no inbound link within its conversation | An orphan. A cross-conversation link from elsewhere may still reach it, which is why this is a warning. |
variable "…" is defined but never used | Not referenced in any condition, script, or [var=…] in any field. |
no branching anywhere (flat script) | No node in the project has more than one outgoing link. |
Performance warnings
Section titled “Performance warnings”Reported only for projects that use the performance fields or performance cues. An unknown or unsupported cue is a no-op at runtime, so these never become errors.
| Rule | Scope |
|---|---|
<channel> "<name>" is not in the performance vocabulary | A node or actor field, or an inline cue, names something no enabled target knows. |
gesture "<name>" is not in the LearnBrite catalogue; it is published as written | LearnBrite mode only. The gesture is passed to the runtime unchanged, since the runtime resolves names this catalogue may not list. |
<channel> "<name>" does nothing on <target> | The name is valid but an enabled target has no way to show it. |
<channel> "<name>": poses only play in LearnBrite mode | A pose in a project without LearnBrite mode. |
<channel> "<name>": intensity n is outside 0 to 1 | On an inline cue, or from Expression_intensity. |
Expression_intensity "…" is not a number | The node field holds non-numeric text. |
gesture "<name>" needs two actors: add a target | A two-avatar gesture (hug, handshake, hi5) with no target. |
performance cue in Menu Text never fires; put it in Dialogue Text | Cues are only read from Dialogue Text and its localized fields. |
Actor "<name>" Expression_palette: "<x>" is not a known expression | An entry in the actor’s comma-separated palette is not an expression. |
Notes for implementers
Section titled “Notes for implementers”- Variable references are found with the pattern
Variable["name"](double quotes). A variable counts as defined if itsFields.Namematches either verbatim or after Lua name cleaning. - Reachability follows only links whose destination is the same conversation, from the single root. A conversation with zero or several roots skips the reachability pass (the root error is reported instead).
- Actor references in
Fields.Actor/Fields.Conversantare parsed as integers;""and"-1"mean unset and are valid. - The validator is pure and dependency-free; the same rules run in the
editor, in the export preflights, and in the interop test matrix. A Python
implementation with the same checks ships in the ChatMapper repository as
tools/validate_scenario.py.
Target preflights
Section titled “Target preflights”Some exports add checks of their own, reported with the export rather than here — the Unity preflight is the main one. The HTML player and Yarn exports report scripts outside the supported Lua subset.