From 0191c0db73d49e6ac126619049a6bae5f2d02334 Mon Sep 17 00:00:00 2001 From: santhreal <64453045+santhreal@users.noreply.github.com> Date: Wed, 22 Jul 2026 00:24:03 -0700 Subject: [PATCH] fix(pairing): treat null approved channel lists as empty pairing.json with "telegram": null crashed is_approved during load. Treat non-list channel entries as an empty allow-list. --- nanobot/pairing/store.py | 2 ++ tests/pairing/test_store.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/nanobot/pairing/store.py b/nanobot/pairing/store.py index 92e75ce3..afafb1ec 100644 --- a/nanobot/pairing/store.py +++ b/nanobot/pairing/store.py @@ -46,6 +46,8 @@ def _load() -> dict[str, Any]: # Convert approved lists to str sets for O(1) lookup. for channel, users in data.get("approved", {}).items(): + if not isinstance(users, list): + users = [] data["approved"][channel] = {str(u) for u in users} return data diff --git a/tests/pairing/test_store.py b/tests/pairing/test_store.py index af38fe70..56c84f5d 100644 --- a/tests/pairing/test_store.py +++ b/tests/pairing/test_store.py @@ -240,3 +240,20 @@ class TestStoreDurability: # Should recover gracefully and act as empty store assert store.list_pending() == [] assert store.is_approved("telegram", "123") is False + + +def test_load_treats_null_approved_channel_list_as_empty(tmp_path, monkeypatch): + """Null approved channel lists must not crash pairing checks. + + JSON stores can contain ``"telegram": null`` after partial edits; treat + that like an empty allow-list, matching corrupt-JSON reset behavior. + """ + path = tmp_path / "pairing.json" + path.write_text( + '{"approved": {"telegram": null, "discord": ["456"]}, "pending": {}}', + encoding="utf-8", + ) + monkeypatch.setattr(store, "_store_path", lambda: path) + assert store.is_approved("telegram", "123") is False + assert store.is_approved("discord", "456") is True + assert store.get_approved("telegram") == []