A section can outlive an ad: when a card's listing left the active pool after compose and has no swipe history, it is absent from the engine's by_id map. breakdown() indexed the missing row without a guard, so one such card 500'd GET /api/section (and /api/listing/{id}) - live incident 2026-11-15: section 57 + delisted listing 298. Degrade to no-signal lines instead. Regression test added; before/after verified on a copy of the live DB (section 500 -> 200; forge rebuild 200).