Skip to content

decrypt_events() ignores keys from extract_conversation_keys() even with set_cache_keys(true) #9

Description

@aunysillyme

Summary

extract_conversation_keys() returns a valid conversation-key map, but decrypt_events() does not see those keys — every event fails with Available versions: [], naming the exact version that extract_conversation_keys() just returned. set_cache_keys(true) is enabled and makes no difference.

Passing the same map to decrypt_event() explicitly works, so the key material and the ciphertext are both fine; only the cache hand-off between the two calls is broken.

Reproduction

Python (chatxdk), against a live group conversation:

engine.set_cache_keys(True)
engine.set_signing_keys(signing_keys)

extracted = engine.extract_conversation_keys(key_change_events)
# -> {'keys': {'1785442942475': b'...'}, 'latest_version': '1785442942475'}

result = engine.decrypt_events(message_events)
# -> messages: 0, errors: 10
# "Crypto error: Decryption failed: Message encrypted with key version
#  '1785442942475' but no matching key found. Available versions: [].
#  Call extract_conversation_keys() first."

engine.decrypt_event(message_events[0], extracted["keys"])
# -> works, returns the Message

The error text advises calling extract_conversation_keys() first, which is exactly what was done immediately before, so the message sends you in a circle.

Impact

decrypt_events() is the documented batch path (Getting Started, step 6: "Use decrypt_events() for batch processing"). As written it returns zero messages for a normal conversation, and the error blames a missing key rather than the cache, so it reads like a key-provisioning problem on the caller's side. Working around it means abandoning the batch API and looping decrypt_event() per event with the map threaded through manually.

Related doc gap

The key-change events that feed extract_conversation_keys() are not in the events response's data array — they arrive in meta.conversation_key_events. That is easy to miss, and getting it wrong produces the identical Available versions: [] error, which makes the two problems hard to tell apart. Worth calling out explicitly in the Getting Started decrypt section.

Environment

  • chatxdk (Python), 2026-07-30
  • xdk 0.6.6
  • Python 3.12, macOS
  • Auth: OAuth 2.0 user context, dm.read / dm.write
  • Identity loaded via import_keys() from an exported key blob; is_unlocked() true, set_reject_unverified(True)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions