Pitfalls: mistakes models make writing Soma
The mistakes an LLM makes writing Soma, each with the actual compiler error and the fix. Every pair below is verified against the current soma binary. This is the self-correction corpus: when soma check / soma run emits one of these errors, apply the paired fix.
A rule of thumb: soma check catches most of these before you run. Write the file, run soma check app.cell, fix what it reports, repeat.
- Quotes inside {...} interpolation
- match arms use ->, not =>
- Handlers don't declare return types
- Adjacent string literals do NOT concatenate
- == IS structural on lists, maps and variants
- Float equality needs a tolerance
- transition() returns a map, not the target string
- is_a recognizes sum-type variants; match is how you branch on them
- There is no cell type X { fields { ... } }
- soma serve routes only the cell that owns request
- Your handler shadows a builtin of the same name — when the argument count matches
- assert_fails needs an expression that RAISES, not a falsy bool
- Slot methods work on declared memory slots, not local maps
- on is a reserved keyword
- No semicolons; statements are newline-separated
- given is reserved (like on)
- What a test cell's rules { } accepts
- An invariant between two slots defaults both sides
- 7 / 2 = 3.5 everywhere — say idiv when you mean the integer quotient
- A cost bound is only proven when every think() count is known
- Habits from Python / TypeScript that soma check now redirects
- Transition guards see the calling handler's locals
- soma.toml is validated
- Handlers are atomic; errors have kinds
- * -> failed leaves EVERY state, final ones included
- A route in request and a handler of the same name
- A flesh body does only what its signal's frame says
- Structure goes in the skeleton, bodies in the flesh
- A helper in a flesh is _private and typed
- transition(id, "x") needs every edge into x in the frame