# `booth marks` / `booth answer` got real exit codes _2026-09-22 · booth_ **`booth marks` / `booth answer` got real exit codes**, because a read that CRASHED was indistinguishable from a read that said no. `marks` printed a traceback and exited 0 (a caller's `jq` saw success and got nothing); `answer --wait` read a damaged file as "not yet" and spun for the full hour before blaming the operator. Now `0 ok · 1 unanswered/timed-out · 2 no such pick · 3 unreadable`, and `read_error()` was added to `marks.py` so the CLI can ask the question the browser must not: the page stays lenient, the machine consumer gets the truth. Also `--wait` now prints ONCE — it was emitting a whole JSON document per poll, so a captured `--wait` held several concatenated values and parsed as none of them.