Error codes

Every problem Talewright reports has a code and a location:

chapters/02-temple.tale:14:23: error TW2002: Unknown scene 'temple.hal'.
└── file ─────────────┘ │  │         └ code ┘ └ message ──────────────┘
                     line column

Errors stop the story from loading. Warnings (marked ⚠) don’t, but usually point at a mistake. When you see several errors, fix the first one and check again: one mistake can cause others.

TW1xxx: writing mistakes in .tale files

Code Meaning Usual fix
TW1001 Something unexpected in a condition or effect. Check spelling and operators, e.g. player:dex >= 12.
TW1002 A number is too large, or @priority isn’t a whole number. Use a whole number.
TW1003 Malformed effect. Stats and variables use =, += or -=. Flags use set flag:x / clear flag:x.
TW1004 A { is never closed. Close it, or write \{ for a literal brace.
TW1005 Unbalanced {if} / {else} / {/if}. Inline conditions must open and close in the same paragraph. Block conditions need their own lines.
TW1006 Bad scene metadata (@title, @hub, @hub-limit, …). Put metadata directly after the === line, once each. @hub-limit needs @hub.
TW1007 Malformed dialogue line. > who: text, where who is a character id.
TW1008 Invalid scene id. Use the shared ASCII identifier form: start with a letter or _, then use letters, digits, _, and single . or - separators, e.g. temple.entrance.
TW1009 Skill check outcomes are missing or misplaced. Every check needs both success: and failure: lines directly below it.
TW1010 -> without a target. -> scene.id or -> END.
TW1011 Malformed choice. * [label] (requires: ...) { effects } -> target. Check for missing ], ) or }.
TW1012 Unknown or unclosed ::: block. Only ::: skill-check is supported, and it ends with :::.
TW1013 Malformed skill check. skill-check [character] skill dc 12.
TW1014 Malformed image call or image string escape. Write {image("path", "alt text")} or {image("path")}. Quote both arguments, separate them with a comma, and use \" or \\ for embedded quotes or backslashes.
TW1015 Old Markdown image syntax. Replace ![alt](path) with {image("path", "alt")}; the message gives the escaped replacement.

TW2xxx: names and types

Code Meaning Usual fix
TW2001 Unknown character, stat, item or faction. Fix the spelling, or declare it in story.talewright.yaml.
TW2002 Unknown scene. Fix the spelling, or add the scene.
TW2003 Wrong kind of value, e.g. assigning text to a number, comparing text with a number, or arithmetic on text. Keep each variable’s declared type. Text uses = and text-to-text == / !=; numbers retain arithmetic. Declare text with a quoted initial value under vars:.
TW2004 A flag or variable is checked but never set. Fix the spelling, set it somewhere, or declare it under flags: / vars:.
TW2005 Unknown @predicate. Named predicates come from C# extensions; check the name or register it.
TW2006 Unknown #modifier. Use #possessive, #capitalize, #upper, #lower or #a.
TW2007 A variable’s integer or text type cannot be inferred, e.g. a circular assignment chain without a known type. Declare an initial value under vars: in the manifest, or fix the unresolved expression. Types are fixed; discovery never executes assignments.
TW2010 Unsafe image path. Use a relative path inside images/, with / separators and no parent traversal, absolute path, web address, query string or fragment.
TW2011 Unsupported image format. Use PNG (.png), JPEG (.jpg or .jpeg), or WebP (.webp).
TW2012 Image file not found. Put the file in the story’s images/ folder and match its path’s case exactly.
⚠ TW2013 An extensionless image path matches several files. Include the extension to choose explicitly. Otherwise the first match wins in .png, .jpg, .jpeg, .webp order.
⚠ TW2014 Image alt text is missing, empty or whitespace-only. Supply descriptive alt text. The fallback is the humanized filename in sentence case, or Image if no words remain.

Story compilation, talewright validate and editor analysis report these image codes through the same resolver. Diagnostics point to the image path’s opening quote in the authored narrative, including dialogue and choices. Malformed image calls receive syntax diagnostics instead of resolver errors. Editors refresh the catalogue and diagnostics when files change. Lookup reads paths, not image bytes; it does not validate file contents or render images. Successful compilation stores the selected story-root-relative path and effective alt text in each media node.

For an unknown skill, check the id’s spelling and its declaration under game.ruleset.stats. Giving a character a value does not declare the skill. See the complete custom skill recipe.

TW3xxx: story structure

Code Meaning Usual fix
TW3001 Text before the first scene, or no .tale files at all. Start each file with === scene.id.
TW3002 Dead end: a scene with no way out. Add choices, -> target or -> END.
TW3003 A choice or check outcome has no target, and the scene has no -> to fall through to. Give it a target or add a -> line to the scene. Also appears as a side effect of TW2002.
TW3005 The ruleset has no skill-check rule. Use the generic ruleset, or remove the checks.
TW3006 More than one ::: skill-check block in a scene, or one inside {if}. Move the check into its own scene.
TW3007 The start scene doesn’t exist. Fix game.start: in story.talewright.yaml.
⚠ TW3008 A hub has no scenes with its tags. Tag some scenes, or fix the hub’s tag.
⚠ TW3009 A scene can never be reached. Link to it, or remove it. Only shown once there are no errors.
TW3010 Two scenes have the same id. Rename one. The message says where the first one is.

TW4xxx: story.talewright.yaml

Code Meaning Usual fix
TW4001 Invalid YAML. Check indentation (spaces, not tabs) and colons.
TW4002 Something required is missing: story.talewright.yaml itself, game.id, game.title, game.start, the player character, a character’s first-name, a stat’s id, or a trigger’s id/when/do. Add it.
TW4003 A value is invalid, e.g. not a number, out of range, or not allowed here. Includes invalid identifiers. Read the message for the allowed values.
TW4004 Unknown ruleset. Use generic or none.
TW4005 Unknown stat or item in story.talewright.yaml. Fix the spelling, or declare it under game.ruleset.stats / items.
⚠ TW4006 Unknown key (ignored). Usually a typo, e.g. charaters:.
TW4007 A declaration identity is repeated, two triggers have the same id, or more than one configuration file declares triggers:. Remove or rename the duplicate; keep one authored trigger list. Cross-file conflicts name both sources.

Lint rule codes

Lint rules use stable TWL IDs, separate from compiler diagnostic codes. They run on shared source-aware analysis and do not replace or duplicate compiler diagnostics. Their severities and per-file suppressions are configured in the optional story-root talewright.lint.json; see the lint CLI reference.

Code Meaning Usual fix
TWL001 A scene ID is not lowercase kebab-case, optionally grouped with dots. Use lowercase words separated by hyphens, and dots to group scenes (for example ending.empty-handed).
TWL002 The manifest story ID is not lowercase kebab-case. Use a short lowercase ID with words separated by hyphens (for example night-ferry).

Command-line codes

talewright validate and talewright lint report these for problems with the command itself rather than the story. See the CLI reference.

Code Meaning
TWCLI001 Invalid command or options.
TWCLI002 An input/output operation failed, an existing publish destination needs --force in noninteractive use, the destination changed during publication, or a required file, tool or desktop component is missing.
TWCLI003 talewright lint configuration is invalid.

Editor and C# project messages

These messages are for authors setting up editor integration or building C# extensions. If you are writing a regular .tale story with the built-in rules, you can skip this section.

Code Meaning Usual fix
TW5001 A C# project uses custom story rules or features that the editor has not been told about. Configure compiler options or export authoring metadata. Editors do not automatically build or run C# project code.
TW5002 The language server cannot analyze the story with its configured metadata. Fix the reported metadata file/data error and refresh it. See language-server configuration.
TWLSP004 The language server cannot read or parse talewright.lint.json. Fix the reported configuration error; live analysis continues with default rule settings until the file is valid.

These docs are maintained with the code in squid-farm/talewright. Found a problem? Open an issue.