From 07c3e02d5c4230da9726e9e280dbba2381d142b9 Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Sat, 25 Jul 2026 21:47:05 -0700 Subject: [PATCH] fix(triggers): treat null runHistory as empty when loading triggers --- nanobot/triggers/local_types.py | 3 ++- tests/triggers/test_local_triggers.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/nanobot/triggers/local_types.py b/nanobot/triggers/local_types.py index d3fa0a28..9dc890ad 100644 --- a/nanobot/triggers/local_types.py +++ b/nanobot/triggers/local_types.py @@ -68,9 +68,10 @@ class LocalTrigger: @classmethod def from_dict(cls, data: dict[str, Any]) -> "LocalTrigger": + raw_history = data.get("runHistory", data.get("run_history", [])) or [] history = [ record if isinstance(record, TriggerRunRecord) else TriggerRunRecord.from_dict(record) - for record in data.get("runHistory", data.get("run_history", [])) + for record in raw_history if isinstance(record, (dict, TriggerRunRecord)) ] return cls( diff --git a/tests/triggers/test_local_triggers.py b/tests/triggers/test_local_triggers.py index d4fd279f..b4d6304c 100644 --- a/tests/triggers/test_local_triggers.py +++ b/tests/triggers/test_local_triggers.py @@ -617,3 +617,21 @@ def test_local_trigger_from_dict_coerces_string_last_run_at_ms() -> None: } ) assert trigger_null.last_run_at_ms is None + + +def test_local_trigger_from_dict_accepts_null_run_history() -> None: + """Null runHistory must load as empty, matching CronJobState.from_store_dict.""" + trigger = LocalTrigger.from_dict( + { + "id": "t1", + "name": "n", + "enabled": True, + "channel": "websocket", + "chatId": "c1", + "sessionKey": "websocket:c1", + "runHistory": None, + "createdAtMs": 1, + "updatedAtMs": 1, + } + ) + assert trigger.run_history == []