{"record":{"id":"767206fbe4d8e44a","repo":"chenhg5/cc-connect","slug":"matrix-encrypt-w","errorCode":null,"errorMessage":"matrix: encrypt: %w","messagePattern":"matrix: encrypt: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/matrix/e2ee.go","lineNumber":239,"sourceCode":"\tch.Close()\n\tclient.StateStore = nil\n\tclient.Store = mautrix.NewMemorySyncStore()\n}\n\n// tryEncryptAndSend attempts to encrypt and send an event if E2EE is available.\n// Returns (true, nil) if handled, (true, err) if handled with error, (false, nil) if not handled.\nfunc (p *Platform) tryEncryptAndSend(ctx context.Context, client *mautrix.Client, roomID id.RoomID, evtType event.Type, content any) (bool, error) {\n\tch := p.getE2EECryptoHelper()\n\tif ch == nil {\n\t\treturn false, nil\n\t}\n\tif !p.isRoomEncrypted(ctx, roomID) {\n\t\treturn false, nil\n\t}\n\n\tencContent, err := ch.Encrypt(ctx, roomID, evtType, content)\n\tif err != nil {\n\t\treturn true, fmt.Errorf(\"matrix: encrypt: %w\", err)\n\t}\n\t_, err = client.SendMessageEvent(ctx, roomID, event.EventEncrypted, encContent)\n\tif err != nil {\n\t\treturn true, fmt.Errorf(\"matrix: send encrypted: %w\", err)\n\t}\n\treturn true, nil\n}\n\nfunc (p *Platform) isRoomEncrypted(ctx context.Context, roomID id.RoomID) bool {\n\tclient := p.getClient()\n\tif client == nil || client.StateStore == nil {\n\t\treturn false\n\t}\n\tss, ok := client.StateStore.(crypto.StateStore)\n\tif !ok {\n\t\treturn false\n\t}\n\tenc, err := ss.IsEncrypted(ctx, roomID)","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/matrix/e2ee.go#L221-L257","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nencContent, err := ch.Encrypt(ctx, roomID, evtType, content)\nif err != nil {\n    return true, fmt.Errorf(\"matrix: encrypt: %w\", err)\n}\n// after\nencContent, err := ch.Encrypt(ctx, roomID, evtType, content)\nif err != nil {\n    slog.Warn(\"matrix: encrypt failed, will retry after sync\", \"room\", roomID, \"err\", err)\n    return true, fmt.Errorf(\"matrix: encrypt: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// Go: before sending, wait for the helper to be initialized and room state synced\nif !p.cryptoReady() { return fmt.Errorf(\"crypto helper not initialized\") }\nif !p.isRoomEncrypted(ctx, roomID) { /* skip encryption path */ }","typeGuard":null,"tryCatchPattern":"sent, err := p.tryEncryptAndSend(ctx, roomID, evtType, content)\nif err != nil && strings.Contains(err.Error(), \"matrix: encrypt\") {\n    // transient key/state issue: resync room members and retry once\n    p.resyncRoomState(ctx, roomID)\n    sent, err = p.tryEncryptAndSend(ctx, roomID, evtType, content)\n}","preventionTips":["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."],"tags":["matrix","e2ee","encryption","megolm"],"backgroundTag":"api-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}