From 3f3e6568c99b44f67375bc35014930474eb0cec1 Mon Sep 17 00:00:00 2001 From: Megan Schott Date: Fri, 3 Jul 2026 17:10:51 -0500 Subject: [PATCH] fix(poller): held-LL precision crashed the whole poll when a held ride had no LL offer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit attr.get("ll", {}) returns None (not {}) when the "ll" key is PRESENT but None — which is exactly a held-LL ride with no current offer (TRON, Seven Dwarfs after Megan set her holds). .get("return_start") then ran on None → AttributeError → the exception propagated to the handler and ABORTED the entire poll, so no alerts fired every 2 min until caught (a CloudWatch alarm surfaced it). Fix: `(attr.get("ll") or {})` — coerce present-but-None to {}. The .get(key, default) default only applies to a MISSING key, not a None value. Follow-up worth doing: wrap the per-attraction alert body in try/except so one ride's bug can never again silence ALL alerts (blast radius was the whole poll). Co-Authored-By: Claude Opus 4.8 --- infra/lambda/poller/index.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/infra/lambda/poller/index.py b/infra/lambda/poller/index.py index ff5562d..e24f97e 100644 --- a/infra/lambda/poller/index.py +++ b/infra/lambda/poller/index.py @@ -470,7 +470,10 @@ def filter_to_favoriters( _held = held_ll_by_ride.get(ride_id) _ll_beats_held = True if _held: - _avail = _parse_iso(attr.get("ll", {}).get("return_start")) + # `or {}` — attr["ll"] is present-but-None for a held-LL + # ride with no current offer; .get(k, {}) would return + # None (default is only used on a MISSING key), crashing. + _avail = _parse_iso((attr.get("ll") or {}).get("return_start")) _held_dt = _parse_iso(_held) _ll_beats_held = bool(_avail and _held_dt and _avail < _held_dt) if (