From c2985488c4834b5cedc92d05950ecb361da7e9c0 Mon Sep 17 00:00:00 2001 From: Christian Gick Date: Fri, 27 Mar 2026 10:51:52 +0200 Subject: [PATCH] fix(MAT-258): fix DeviceStore API for Olm to-device E2EE key delivery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit matrix-nio's DeviceStore has no .get() method. Use correct API: DeviceStore[user_id].get(device_id) returns OlmDevice from inner dict. Also fix keys_claim() to accept Dict[str, List[str]] per nio API. This was the root cause of Element X silence — bot couldn't deliver its E2EE key via Olm-encrypted to-device messages, so Element X couldn't decrypt bot's audio frames. Co-Authored-By: Claude Opus 4.6 (1M context) --- bot.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index a4cdd3c..2d48f94 100644 --- a/bot.py +++ b/bot.py @@ -3759,12 +3759,20 @@ class Bot: for user_id, device_id in targets: # Get the device from the device store - device = olm.device_store.get(user_id, device_id) if hasattr(olm, 'device_store') else None + # nio DeviceStore[user_id] returns Dict[str, OlmDevice] + device = None + try: + device = olm.device_store[user_id].get(device_id) + except KeyError: + pass if not device: # Need to fetch device keys first logger.info("Fetching device keys for %s/%s", user_id, device_id) await self.client.keys_query() - device = olm.device_store.get(user_id, device_id) if hasattr(olm, 'device_store') else None + try: + device = olm.device_store[user_id].get(device_id) + except KeyError: + pass if not device: logger.warning("Device %s/%s not found in store, sending unencrypted", user_id, device_id) @@ -3776,7 +3784,7 @@ class Bot: if not session: # Claim one-time key and create session logger.info("Claiming one-time key for %s/%s", user_id, device_id) - claim_resp = await self.client.keys_claim(user_id, device_id) + await self.client.keys_claim({user_id: [device_id]}) session = olm.session_store.get(device.curve25519) if session: