Table of Contents

Error codes

DialogueDown reports each problem it finds as a diagnostic with a stable DLG#### code, so a message is easy to look up. A code's leading digit names its category — DLG1xxx syntax, DLG2xxx semantic, DLG3xxx style — and each diagnostic has a default severity: Error (must be fixed), Warning (compiles but is suspect), or Info (a neutral note). Placeholders such as {0} are filled with specifics — a name, a count — when the message is shown.

Syntax (DLG1xxx)

The script's surface: text that does not parse as intended, or Markdown that never becomes dialogue.

DLG1003

Warning · Unreachable content after a jump

Content after a jump on this line can never play: a jump does not return, so anything following it is unreachable. Move it before the jump, or onto its own line.

A jump does not return, so text or a second jump after it on the same line never plays. Put each jump on its own line, separated by a blank line, so nothing trails it.

Triggering example

# Crossroads
=> [Market](#market) or => [Home](#home)

# Market
Merchant: Wares!

# Home
Alice: Cozy.

Fix

# Crossroads
=> [Market](#market)

=> [Home](#home)

# Market
Merchant: Wares!

# Home
Alice: Cozy.

DLG1101

Error · Tags without a speaker

"{0}" has tags but names no speaker for them to attach to. Begin the line with a name to declare a speaker (Alice #excited:), or with an @id to add tags to an already-declared one (@alice #excited:).

A line that begins with tags but no name has nothing to attach the tags to. Start the line with a speaker's name, or use an @id to add tags to a speaker already declared.

Triggering example

# Scene
#excited: We made it!

Fix

# Scene
Alice #excited: We made it!

DLG1102

Error · Not a game call

"{0}" is not a game call. Write a query that reads a value ("key"), a default command (("do something")), or a named command (Name("arg", ...)).

A code span calls into the game. Its contents must be a query that reads a value, a default command, or a named command — plain words are not a call.

Triggering example

# Scene
Alice: The sky turns `just some words`.

Fix

# Scene
Alice: The sky turns `"World.Weather"`.

DLG1103

Error · Disallowed element in a label

{0} is not allowed inside a label or alt text; only text and styling are.

A jump or link label is plain, styled text only. Functional elements — code spans, images, nested links, or line breaks — are not allowed inside a label or an image's alt text.

DLG1104

Error · Missing weight in a random choice

This option has no weight, but its list is a random choice. Give it a weight like 50%, or % to share the remaining percentage equally.

In a random choice — a list where at least one option leads with a weight — every option must carry a weight so the engine can pick fairly. Give the option a percentage like 50%, or % to share the remaining percentage equally.

Triggering example

# Coin
The coin spins.

- `50%` Heads.
- Tails.

Fix

# Coin
The coin spins.

- `50%` Heads.
- `50%` Tails.

DLG1105

Error · Invalid choice weight

"{0}" is not a valid weight. Write a non-negative percentage like 50%, or % to share the remaining percentage equally.

A choice weight is a percentage code span: a non-negative number like 50%, a bare % to take an equal share of the remaining percentage, or a game-state key like Luck% the runtime computes into a weight. A negative number is not a valid weight.

Triggering example

# Coin
The coin spins.

- `-10%` Heads.
- `%` Tails.

Fix

# Coin
The coin spins.

- `10%` Heads.
- `%` Tails.

DLG1106

Error · Condition guards nothing

A condition ("{0}"?) must guard a jump, line, choice option, or control branch. Put it immediately before a => jump, at the start of a line or choice option, or after an if/elseif marker; otherwise remove the ? to write a plain query.

A condition guards the jump it precedes, the line it fronts, the choice option it leads, or the control branch it opens. A "key"? code span anywhere else has nothing to guard. Move it to one of those positions, or remove the ? to write a plain query.

Triggering example

# Moor
Guide: `"Rainy"?` The moor is bleak.

Fix

# Moor
`"Rainy"?` Guide: The moor is bleak.

DLG1107

Warning · Styled speaker prefix

This line looks like a speaker prefix ("{0}") but the name is styled, so it is not recognized and the line has no speaker. Remove the styling to declare the speaker.

A line that begins with a styled name followed by a colon — like *Alice*: — looks like a speaker prefix, but the styling stops it from being recognized, so the line has no speaker. Remove the styling from the name.

Triggering example

*Alice*: Hello there.

Fix

Alice: Hello there.

DLG1108

Error · Severed control branch

{0} starts a separate blockquote without a connected if. Keep the if, every elseif, and the optional else inside one connected blockquote.

Every branch of a block conditional belongs to one connected blockquote. An elseif or else that starts another blockquote has no connected if; continue the original blockquote instead.

Triggering example

> `elseif` `Known?`
>
> Alice: Welcome back.

Fix

> `if` `Known?`
>
> Alice: Welcome back.

DLG1109

Error · Malformed control branch order

{0} cannot appear here. A control block must contain one if, followed by zero or more elseif branches, then at most one else.

A block conditional has one if, then any elseif branches, then at most one else. Move a conditional branch before the fallback instead of adding another else afterward.

Triggering example

> `if` `Rich?`
>
> Alice: Welcome upstairs.
>
> `else`
>
> Alice: Try downstairs.
>
> `else`
>
> Alice: Welcome back.

Fix

> `if` `Rich?`
>
> Alice: Welcome upstairs.
>
> `elseif` `Known?`
>
> Alice: Welcome back.
>
> `else`
>
> Alice: Try downstairs.

DLG1110

Error · Control marker must stand alone

A {0} marker must stand alone in its paragraph. Put a quoted blank line (>) between the marker and its branch body.

A branch marker is its own paragraph. Keep the blockquote connected, but add a quoted blank line (>) before the branch body so Markdown does not fuse them together.

Triggering example

> `if` `Rich?`
> Alice: Welcome upstairs.

Fix

> `if` `Rich?`
>
> Alice: Welcome upstairs.

DLG1111

Error · Missing control branch condition

A {0} marker requires a condition in a separate code span, such as {0} Rich?.

An if or elseif marker needs its condition in a second code span. Add a condition such as Rich?; only else is unconditional.

Triggering example

> `if`
>
> Alice: Welcome upstairs.

Fix

> `if` `Rich?`
>
> Alice: Welcome upstairs.

DLG1112

Error · Else branch cannot have a condition

An else marker cannot have the condition {0}?. Remove the condition for a fallback branch, or change else to elseif.

An else is the unconditional fallback, so it cannot carry a condition. Remove the condition, or write elseif when the branch should be conditional.

Triggering example

> `if` `Rich?`
>
> Alice: Welcome upstairs.
>
> `else` `Known?`
>
> Alice: Welcome back.

Fix

> `if` `Rich?`
>
> Alice: Welcome upstairs.
>
> `else`
>
> Alice: Welcome back.

DLG1113

Warning · Dangling jump arrow

=> makes a jump only when a link follows it. With no link here it is read literally, staying as the characters "=>". If you meant to jump, add a target: => [The market](#the-market). If you meant the characters, escape the arrow: \=>.

=> is the jump sigil: it becomes a jump only when a Markdown link follows it. With no link there is nothing to jump to, so the arrow is read literally — it stays on the page as the two characters and the script simply continues to the next line. When the characters are deliberate, escape the arrow (\=>) to say so. When you meant to jump, give it a target.

Triggering example

# Crossroads
Alice: Which way?

=> The market

# The market
Merchant: Wares!

Fix

# Crossroads
Alice: Which way?

=> [The market](#the-market)

# The market
Merchant: Wares!

DLG1114

Info · Markdown left out of the script

This {0} is not dialogue, so the compiler left it out of the script. That is expected for notes and diagrams; write it as dialogue if it should be spoken.

DialogueDown models the Markdown a dialogue needs; everything else is an authoring aid. A code block, a table, or a divider is left out of the script rather than spoken, which is usually the point — a diagram or a note belongs beside the dialogue, not in it. If that is what you meant, keep it: this is a note, not a fault, and nothing about the compile changes. It exists so the omission is never a surprise. If the construct was meant to shape the dialogue, write it in DialogueDown's own terms — a scene break is a heading. If it arrived by accident, remove it.

Triggering example

# Chapter One

Alice: We should go.

---

Alice: The road was long.

Fix — if it was meant to break the scene

# Chapter One

Alice: We should go.

# On The Road

Alice: The road was long.

Fix — if it arrived by accident

# Chapter One

Alice: We should go.

Alice: The road was long.

Semantic (DLG2xxx)

A meaning-level problem found during analysis — a reference that does not resolve, or a conflict.

DLG2001

Error · Duplicate scene anchor

Two scenes resolve to the same anchor '#{0}'. Rename one heading so each jump target is unambiguous.

Each scene heading becomes a jump target — an anchor slugged from its text. Two headings with the same text produce the same anchor, so a jump to it is ambiguous.

Triggering example

# Chapter
Alice: Hello.

# Chapter
Bob: Goodbye.

Fix

# Chapter One
Alice: Hello.

# Chapter Two
Bob: Goodbye.

DLG2002

Error · Heading without an anchor

A heading needs at least one letter or number so it can be a jump target; this one has none. Add sluggable text to the heading.

A heading becomes a jump target only if it has letters or numbers to slug into an anchor. A heading of punctuation alone can never be jumped to.

Triggering example

# ...
Alice: Hello.

Fix

# Prologue
Alice: Hello.

DLG2003

Error · Ambiguous speaker binding

Cannot bind name '{0}' to id '@{1}': both are already in use as separate speakers, so joining them now is ambiguous. If they are the same speaker, declare it (Name @{1}: …) before either is used on its own.

A name and an @id were each used on their own for different speakers, so binding them together now is ambiguous. Declare the pairing once, up front, before either is used alone.

Triggering example

Alice: Hello.

@A: Over here.

Alice @A: It is me.

Fix

Alice @A: It is me.

Alice: Hello.

@A: Over here.

DLG2004

Error · Id bound to two names

id '@{0}' is already bound to speaker '{1}', so it cannot also be bound to '{2}'. Use a different id for '{2}'.

An @id is a stable handle for one speaker, so it cannot name two. Give the second speaker its own id.

Triggering example

Alice @A: Hi.

Bob @A: Hello.

Fix

Alice @A: Hi.

Bob @B: Hello.

DLG2005

Error · Name bound to two ids

Speaker '{0}' is already bound to id '@{1}', so it cannot also be bound to id '@{2}'. Give the speaker a single id.

A speaker has one stable @id. Binding the same name to a second id is a conflict — give the speaker a single id everywhere.

Triggering example

Alice @A: Hi.

Alice @B: Hello again.

Fix

Alice @A: Hi.

Alice @A: Hello again.

DLG2006

Error · More than one default speaker

Two speakers are marked ##default ('{0}' and '{1}'); only one default speaker is allowed.

The default speaker covers lines that name no one, so a script can have only one. Mark just a single speaker ##default.

Triggering example

Alice ##default: Hi.

Bob ##default: Hello.

Fix

Alice ##default: Hi.

Bob: Hello.

DLG2007

Error · Unnamed speaker id

Speaker '@{0}' is used but never declared with a name. Declare it with a name (Name @{0}: …) — a stable id must belong to a named speaker.

A stable @id must belong to a named speaker. This id is referenced but never declared with a name — declare it once with Name @id:.

Triggering example

# Scene
@ghost: Who goes there?

Fix

# Scene
Ghost @ghost: Who goes there?

DLG2008

Error · Unknown reserved tag

'##{0}' is not a known reserved tag. Use a custom tag ('#{0}') or one of DialogueDown's reserved tags.

A ##name tag is a reserved, built-in tag, and ##default is the only one DialogueDown knows. For your own metadata use a custom tag with a single #.

Triggering example

# Scene
Alice ##hero: To the rescue!

Fix

# Scene
Alice #hero: To the rescue!

DLG2009

Error · Jump to a missing scene

Jump target '#{0}' does not match any scene. Check the anchor, or add a heading it can point to.

A jump must point at a scene that exists in the file. This jump's anchor matches no heading — check the spelling, or add the scene it should reach.

Triggering example

# Start
Alice: Onward!

=> [Continue](#the-end)

Fix

# Start
Alice: Onward!

=> [Continue](#the-end)

# The End
Alice: We made it.

DLG2010

Error · Random choice weights sum to zero

Every weight in this random choice is 0, so no option can be selected. Give at least one option a positive weight.

A random choice picks one option by weight. When every weight is 0 there is nothing to pick from — the odds are undefined. Give at least one option a positive weight.

Triggering example

# Coin
The coin spins.

- `0%` Heads.
- `0%` Tails.

Fix

# Coin
The coin spins.

- `50%` Heads.
- `50%` Tails.

DLG2015

Error · Scene heading inside a branch

A scene heading must be a document-level block; it cannot appear inside a control branch or choice option. Move the heading outside the branch, then jump to that scene when the branch should enter it.

Scene headings define document-level jump targets. A heading inside a control branch or choice option would not create a scene, so move it outside the branch and jump to it when that path should enter the scene.

Triggering example

> `if` `Rich?`
>
> # Upstairs
>
> Alice: Welcome.

Fix

# Upstairs

> `if` `Rich?`
>
> Alice: Welcome.

DLG2016

Warning · Jump outside this script is not resolved yet

This jump names '{0}', which is outside this script. Targets outside the script are not resolved yet, so the jump leads nowhere. Point it at a scene in this script — '#the-scene' — until cross-file jumps land.

A jump reaches a scene in the script it is written in. Reaching one in another script is not built yet, so a target naming a file or a URL resolves to nothing and the line simply reads on. Keep the destination in this script until cross-file jumps land.

Triggering example

Alice: To the vault.

=> [The vault](chapter-02.md#the-vault)

Fix

Alice: To the vault.

=> [The vault](#the-vault)

# The vault

DLG2017

Warning · Option with nothing to show

Nothing here names this option, so a player is offered a blank line to pick. Give the option something to say, or name the jump it makes: - => [Take the east road](#the-market).

A menu shows each option by the words written in it — the line it speaks, or the text of the jump it makes. An option with neither leaves the player a blank line to pick. The compiler will not read words off the scene the option leads to, because those belong to whoever wrote them, so the option stays as blank as it was written.

Triggering example

Alice: Which way?

- `("fade out")`
- Alice: Stay here.

Fix

Alice: Which way?

- Slip away quietly `("fade out")`
- Alice: Stay here.

Style (DLG3xxx)

A valid script that reads correctly but could read better.

DLG3002

Warning · Deeply nested choice branch

This branch reaches choice nesting level {0}; the recommended maximum is {1}. Consider moving this branch into a new scene and jumping to it instead.

Nested choices remain valid, but a fourth level becomes difficult to scan and maintain. Consider moving that branch into a new scene and jumping to it instead.

Triggering example

# Conversation

- Level 1
    - Level 2
        - Level 3
            - Level 4
                Alice: This branch is difficult to scan.

Fix

# Conversation

- Level 1
    - Level 2
        => [Continue](#deeper-branch)

# Deeper branch

- Level 3
    - Level 4
        Alice: This branch is easier to scan.

DLG3003

Warning · Choice weights do not total 100%

These weights total {0}%, not 100%. Weights are normalized by their sum, so the odds still work; adjust them to total 100% to state the intended odds directly.

A random choice's weights are relative — they are normalized by their sum — so any positive total works. When they do not add up to 100 the intended odds are harder to read; adjust them to total 100% (or use % to share the rest) to state the odds directly.

Triggering example

# Coin
The coin spins.

- `50%` Heads.
- `30%` Tails.

Fix

# Coin
The coin spins.

- `50%` Heads.
- `50%` Tails.

DLG3004

Warning · Single-option random choice

This random choice has a single option, so it is always selected and the weight has no effect. Remove the weight to make it a plain line, or add more options.

A random choice with only one option always selects it — the weight has no effect and the list is not really random. This usually means a plain line was given a weight, or the other options are missing.

Triggering example

# Coin
The coin spins.

- `50%` It always lands heads.

Fix

# Coin
The coin spins.

- `50%` Heads.
- `50%` Tails.