chenhg5/cc-connect · error
matrix: encrypt: %w
Error message
matrix: encrypt: %w
What it means
This error wraps a failure from ch.Encrypt() inside tryEncryptAndSend. After confirming the room is encrypted, the adapter encrypts the event content with Megolm for the target room; if the crypto helper cannot produce encrypted content (no group session, unknown room members, missing outbound session), the send is aborted with this wrapped error instead of sending plaintext.
Source
Thrown at platform/matrix/e2ee.go:239
ch.Close()
client.StateStore = nil
client.Store = mautrix.NewMemorySyncStore()
}
// tryEncryptAndSend attempts to encrypt and send an event if E2EE is available.
// Returns (true, nil) if handled, (true, err) if handled with error, (false, nil) if not handled.
func (p *Platform) tryEncryptAndSend(ctx context.Context, client *mautrix.Client, roomID id.RoomID, evtType event.Type, content any) (bool, error) {
ch := p.getE2EECryptoHelper()
if ch == nil {
return false, nil
}
if !p.isRoomEncrypted(ctx, roomID) {
return false, nil
}
encContent, err := ch.Encrypt(ctx, roomID, evtType, content)
if err != nil {
return true, fmt.Errorf("matrix: encrypt: %w", err)
}
_, err = client.SendMessageEvent(ctx, roomID, event.EventEncrypted, encContent)
if err != nil {
return true, fmt.Errorf("matrix: send encrypted: %w", err)
}
return true, nil
}
func (p *Platform) isRoomEncrypted(ctx context.Context, roomID id.RoomID) bool {
client := p.getClient()
if client == nil || client.StateStore == nil {
return false
}
ss, ok := client.StateStore.(crypto.StateStore)
if !ok {
return false
}
enc, err := ss.IsEncrypted(ctx, roomID)View on GitHub (pinned to 4000b2338a)
Solutions
- Ensure crypto init completed (ch.Init succeeded) before sending; log/wait for initial sync and device-list readiness.
- Wait for or force a room-state sync so member device lists are populated, then retry the send.
- Verify members' devices can share keys (cross-signing/verification); run the stale-key re-upload path if server keys are out of sync.
- If persistent, close and recreate the CryptoHelper to rebuild outbound sessions.
- Log the wrapped cause to distinguish 'no Olm session with member' from generic store failures.
Example fix
// before
encContent, err := ch.Encrypt(ctx, roomID, evtType, content)
if err != nil {
return true, fmt.Errorf("matrix: encrypt: %w", err)
}
// after
encContent, err := ch.Encrypt(ctx, roomID, evtType, content)
if err != nil {
slog.Warn("matrix: encrypt failed, will retry after sync", "room", roomID, "err", err)
return true, fmt.Errorf("matrix: encrypt: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// Go: before sending, wait for the helper to be initialized and room state synced
if !p.cryptoReady() { return fmt.Errorf("crypto helper not initialized") }
if !p.isRoomEncrypted(ctx, roomID) { /* skip encryption path */ } Try / catch
sent, err := p.tryEncryptAndSend(ctx, roomID, evtType, content)
if err != nil && strings.Contains(err.Error(), "matrix: encrypt") {
// transient key/state issue: resync room members and retry once
p.resyncRoomState(ctx, roomID)
sent, err = p.tryEncryptAndSend(ctx, roomID, evtType, content)
} Prevention
- Treat 'bot added to encrypted room' as an async event: delay sends until first full sync completes.
- Never delete the crypto DB while the room remains encrypted; back it up instead.
- Enable device-list tracking and key-share responses from your other sessions.
- Add observability around Encrypt failures to distinguish missing-member-keys vs session errors.
When it happens
Trigger: sendRoomEvent → tryEncryptAndSend: isRoomEncrypted returns true and ch.Encrypt(ctx, roomID, evtType, content) returns err — e.g. no outbound Megolm session could be created because room member keys/device lists are unknown, the crypto helper was not fully initialized, or the room state store lacks membership data.
Common situations: Bot was just invited to an encrypted room and has not yet received member device keys; encryption configured server-side but the local crypto DB was deleted so sessions are missing; key share requests from other devices pending/unanswered; room state store not synced before first send.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- device ID not available from whoami
- get home dir: %w
- create data dir: %w
- create crypto helper: %w
- init crypto: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/767206fbe4d8e44a.
Report an issue: GitHub.