Why Verse Fails
beginner
4 lessons ·
~100 min · Generated 2026-07-17
Every Verse tutorial shows you code that works — and then you meet the real compiler. This track is different: every lesson is taught FROM real errors, captured from real builds, with the fix and the why. By the end, a wall of red output is a thirty-second repair. The compiler was never fighting you; it was teaching.
Prerequisites
Learning Outcomes
- Read error 3512 in both its faces and fix the contract, not the position
- Call might-fail functions with [] and give every question a failure plan
- Name the silent no_rollback default on sight and annotate pure helpers <transacts>
- Tell a real compiler rule from a folk rule
- Repair 3506/3513/3581/3100/3596 in thirty seconds each — and read cascades top-down
Lesson 1: Failure Is a Feature
Objectives
- Read errors 3511 and 3512: failure contexts, <decides>, and why the compiler rejecting your code is the language working.
Read errors 3511 and 3512: failure contexts, <decides>, and why the compiler rejecting your code is the language working.
Quiz
- Why does `FirstKey := KeyNames[0]` fail to compile on its own line?
- A. Arrays must be declared var to be indexed
- B. Indexing might fail, so it needs a failure context with a plan for that
- C. KeyNames is immutable so it cannot be read
- D. Verse requires FirstKey to be declared with a type
- What does Script error 3511 tell you?
- A. The function does not exist
- B. You used square brackets on a function that always succeeds
- C. You used parentheses to call a function that might fail — decides calls need []
- D. The function is missing a return type
- What does a <decides> function's body return?
- A. true or false
- B. An option value
- C. Nothing — succeeding or failing IS the answer
- D. An error code
- Which of these is a failure context, per the compiler's own error text?
- A. The right-hand side of an assignment
- B. The condition clause of an if
- C. A Print argument
- D. A class field default
- Why does `IsLocked : logic = State = door_state.Locked` fail?
- A. logic is not a real Verse type
- B. Enums can only be compared with case
- C. = comparison can fail, and a plain assignment is not a failure context
- D. State must be declared without var
Answer key
- B — Array indexing carries the decides effect — the index might not exist — so it may only appear in a failure context like an if condition.
- C — Brackets tell the truth about failure: () for calls that always succeed, [] for <decides> calls that might fail.
- C — A decides function doesn't return a boolean; its body is the test, and success or failure is the result the caller handles.
- B — Error 3512 lists them: the condition clause of an if, the left operand of or, the clause of the logic macro.
- C — In Verse, = comparison succeeds-or-fails (it carries decides), so it must sit in a failure context — ask the question in an if instead of storing a flag.
Sources
- /guides/why-verse-fails-1-failure-is-a-feature
Lesson 2: The Effects System
Objectives
- Function contracts, the silent no_rollback default, and effect transitivity — 3512's second face.
Function contracts, the silent no_rollback default, and effect transitivity — 3512's second face.
Quiz
- What effect does an unannotated Verse function have?
- A. <transacts>
- B. <decides>
- C. no_rollback — its work cannot be undone
- D. No effect at all
- Why do failure contexts only allow rollback-safe work?
- A. For performance
- B. A failed attempt is UNDONE as if it never happened — so everything inside must be undoable
- C. Because devices are slow
- D. It's a style convention
- A pure math helper fails 3512 when called in an if condition. The fix?
- A. Move the call out of the if
- B. Annotate the helper <transacts>
- C. Mark the helper <decides>
- D. Wrap it in spawn{}
- Why can't a function that calls GrantItemIndex be marked <transacts>?
- A. It can, with the right using
- B. Granting a real item can't be undone — the native call is no_rollback and your annotation can't change that
- C. GrantItemIndex is <decides>
- D. Device methods need <suspends>
- What does 'effects are transitive' mean?
- A. Effects only apply inside classes
- B. A <transacts> function may only call <transacts>-or-stricter functions — one unannotated callee breaks the chain
- C. Effects copy to subclasses
- D. suspends implies decides
Answer key
- C — The silent default: a function with no annotation is no_rollback. Pure helpers must opt IN to <transacts>.
- B — Failure contexts roll back the failed attempt; no_rollback work can't be un-rung.
- B — Rule of thumb: annotate pure helpers <transacts> — a promise a compute-only function can honestly make.
- B — You can't promise to undo a granted item. Leave world-touching callers undecorated — the signature then tells the truth.
- B — Contracts flow through call chains: a promise-keeper may only call other promise-keepers.
Sources
- /guides/why-verse-fails-2-the-effects-system
Lesson 3: One Rule, Four Costumes
Objectives
- The allocation myth retired by gate probes: annotate the effect — position never mattered.
The allocation myth retired by gate probes: annotate the effect — position never mattered.
Quiz
- Is `if (Prices := map{{...}}, Cost := Prices[K]):` legal Verse?
- A. No — allocation in a condition is always illegal
- B. Yes — construction is rollback-safe; this compiles with zero errors
- C. Only if the map is empty
- D. Only inside OnBegin
- A helper returning a map fails 3512 when called in a condition. What's the actual defect?
- A. Maps can't be returned from functions
- B. The helper is unannotated, so it defaults to no_rollback
- C. The condition has too many binders
- D. Maps require <suspends>
- What does hoisting a call out of a condition actually do?
- A. Fixes the effect contract
- B. Works incidentally — it moves the unannotated call out of the restricted position without fixing the contract
- C. Makes the call rollback-safe
- D. Nothing; hoisted code fails the same way
- Which position is restricted like an if condition?
- A. A case arm
- B. A for loop's iterable position
- C. OnBegin's body
- D. A Print argument
- Why is a device call like GrantItemIndex legal inside a case arm?
- A. case arms are failure contexts with special handling
- B. A case arm is NOT a failure context — nothing rolls back there, so no_rollback work is at home
- C. Device calls are exempt from all effect rules
- D. It isn't legal
Answer key
- B — Gate-verified: a map literal directly in the condition binder compiles clean. Allocation was never the crime.
- B — The silent default — annotate the pure helper <transacts> and the same call in the same position compiles.
- B — Hoisting works by relocation, not repair. Annotate the helper; then place the call wherever reads best.
- B — The for-iterable is a restricted position — an unannotated helper there fails the same 3512; annotated, it's legal in place.
- B — Knowing where restrictions END matters: case dispatch doesn't undo anything, so world-changing calls belong there freely.
Sources
- /guides/why-verse-fails-3-one-rule-four-costumes
Lesson 4: Reading the Compiler
Objectives
- The error-code field guide + cascade-reading: every string from real builds, every fix thirty seconds.
The error-code field guide + cascade-reading: every string from real builds, every fix thirty seconds.
Quiz
- What is the single most common compile failure family in real Verse projects?
- A. 3512 effects errors
- B. 3506 unknown identifier — a name the file can't see (usually a missing using)
- C. 3100 parse errors
- D. 3581 break placement
- What's the fix loop?
- A. Delete and rewrite the function
- B. Read the code + quoted term → find the position → apply the family rule → recompile
- C. Comment out lines until it compiles
- D. Ask the forum
- 3513 'expected an expression that can fail' fires on `if (DoorOpen):` where DoorOpen is logic. Fix?
- A. Declare DoorOpen as int
- B. Postfix ? — `if (DoorOpen?):` turns the logic into a failable question
- C. Wrap it in spawn{}
- D. Use case instead
- You want to stop a `for` early and the compiler says 3581. What's idiomatic?
- A. Add <breakable> to the for
- B. Put the walk in its own function and return on the hit (or use loop:)
- C. break twice
- D. Use a while loop
- A 31xx vErr error means…
- A. An effects contract broke
- B. The parser couldn't read the line's SHAPE — look for missing braces or stray tokens
- C. The file is too long
- D. A missing using
Answer key
- B — By a wide margin: 3506. And the error text usually names the exact using to add.
- B — Every error in the guide is a thirty-second repair once read this way.
- B — A condition wants a question that can fail; ? makes a logic succeed-if-true, fail-if-false.
- B — break is loop-only in Verse; for-early-exit restructures to return-from-function or loop:.
- B — 31xx = syntax shape, not semantics: bare `spawn Tick()` needs `spawn{ Tick() }`.
Sources
- /guides/why-verse-fails-4-reading-the-compiler
Generated by Verse Island on 2026-07-17.