Dead ends and unreachable nodes: what a dialogue tree checker can and cannot prove
Two classes of dialogue-tree bug are decidable by machine, one is not, and knowing which is which tells you where to spend your attention.
Published
Dialogue trees fail in a small number of ways, and it is worth being precise about which ones a tool can settle for you, because the answer is not “all of them” and it is not “none of them”.
The two decidable ones
A dialogue tree has two failure modes a machine can settle completely: a dead end is a node with no outgoing edge that is not marked terminal, and an unreachable node is one with no path from any entry point. Both are ordinary graph questions, decidable in one pass, and neither depends on taste. What a checker cannot settle is whether a reachable node is reachable in the state the player will actually be in — that requires reasoning about the flags guarding each edge, which is a different and much harder problem.
Dead ends show up in play as a conversation that stops with no way to leave — the player is stuck in a dialogue camera with no options. They are almost always introduced by editing: a node had two replies, one got cut during a rewrite, and the remaining one was the branch that got moved somewhere else.
Unreachable nodes are the opposite and are much more common. Someone writes a branch, restructures the conversation above it, and the branch is still in the file with nothing pointing at it. Nobody notices, because the failure mode is absence: content that never appears looks exactly like content that was never written. The cost is real, though — it is written, reviewed, possibly voiced, and it does nothing.
The one that is not decidable in the same way
Ask whether a node is reachable given the flags and you have left graph theory. Edges are guarded by conditions over game state; whether a combination of conditions can be satisfied depends on what else in the game sets those flags, in what order, under what constraints.
This is the class that contains soft locks — the player reaches a state where a required conversation can no longer be triggered. It is genuinely hard, and it is the class where formal methods earn their keep. If you want it proved rather than sampled, you want a solver, and there is serious work happening in that direction in the Yarn Spinner ecosystem.
We do not try to compete there. We do the graph-decidable checks completely, register every flag that quests read and write so the state is at least enumerable, and simulate playthroughs to sample the state space rather than claiming to have proved it.
The classes nobody’s checker will settle
Two more failure modes matter and are not mechanical at all:
- A branch that is reachable but pointless. Three options that converge on the same next node with no state change between them. Structurally perfect; a lie to the player. The check is whether the branches differ in what they change, and that is a design judgement.
- A character speaking out of voice. Structurally invisible. This is why voice bibles are worth writing down before dialogue is generated rather than after — a defined register, a set of verbal tics, and an explicit list of words this character would never use gives a reviewer something to check against, instead of a feeling that something is off.
Where to spend your attention
Automate the two decidable classes and stop thinking about them — they are cheap to check, they recur endlessly, and every hour spent finding them by hand is an hour not spent on the two that need you. Sample the state-dependent class deliberately rather than hoping playtesting covers it. And spend the attention you have freed on whether the branches mean anything, because nothing is going to do that part for you.