{"record":{"id":"bfbd60a0b6c8def7","repo":"RocketChat/Rocket.Chat","slug":"error-no-suggested-key-available","errorCode":"error-no-suggested-key-available","errorMessage":"No suggested key available","messagePattern":"No suggested key available","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/lib/e2e/functions/handleSuggestedGroupKey.ts","lineNumber":23,"sourceCode":"\nexport async function handleSuggestedGroupKey(\n\thandle: 'accept' | 'reject',\n\trid: string,\n\tuserId: string | null,\n\tmethod: string,\n): Promise<void> {\n\tif (!userId) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { method });\n\t}\n\n\tconst sub = await Subscriptions.findOneByRoomIdAndUserId(rid, userId);\n\tif (!sub) {\n\t\tthrow new Meteor.Error('error-subscription-not-found', 'Subscription not found', { method });\n\t}\n\n\tconst suggestedKey = String(sub.E2ESuggestedKey ?? '').trim();\n\tif (!suggestedKey) {\n\t\tthrow new Meteor.Error('error-no-suggested-key-available', 'No suggested key available', { method });\n\t}\n\n\tif (handle === 'accept') {\n\t\t// A merging process can happen here, but we're not doing that for now\n\t\t// If a user already has oldRoomKeys, we will ignore the suggested ones\n\t\tconst oldKeys = sub.oldRoomKeys ? undefined : sub.suggestedOldRoomKeys;\n\t\tawait Subscriptions.setGroupE2EKeyAndOldRoomKeys(sub._id, suggestedKey, oldKeys);\n\t\tconst { modifiedCount } = await Rooms.removeUsersFromE2EEQueueByRoomId(sub.rid, [userId]);\n\t\tif (modifiedCount) {\n\t\t\tvoid notifyOnRoomChangedById(sub.rid);\n\t\t}\n\t}\n\n\tif (handle === 'reject') {\n\t\tconst { modifiedCount } = await Rooms.addUserIdToE2EEQueueByRoomIds([sub.rid], userId);\n\t\tif (modifiedCount) {\n\t\t\tvoid notifyOnRoomChangedById(sub.rid);\n\t\t}","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/e2e/functions/handleSuggestedGroupKey.ts#L5-L41","documentation":"The user is subscribed to the room, but the subscription's E2ESuggestedKey is null, empty, or whitespace-only, so there is no suggested key to accept or reject. Accepting a key clears/consumes the suggestion, so repeat or late actions hit this guard.","triggerScenarios":"Calling accept/reject after the suggested key was already consumed by a prior accept (which writes the group key and removes the user from the E2EE queue), or when the key was never distributed to this subscription.","commonSituations":"Double-submitting the suggested-key dialog; another session or device already accepted the key; race between key distribution and the user acting.","solutions":["Reload the room/subscription — if the key was already accepted, the action is unnecessary","If a new key is expected, have a member holding the current room key re-trigger key distribution, then retry"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const sub = await Subscriptions.findOneByRoomIdAndUserId(rid, userId);\nconst hasSuggestedKey = Boolean(String(sub?.E2ESuggestedKey ?? '').trim());\n// only show the accept/reject prompt when hasSuggestedKey is true","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Re-fetch the subscription immediately before showing the suggested-key prompt","Disable the accept/reject button after the first submit to avoid double consumption"],"tags":["e2e","encryption-key","subscription"],"backgroundTag":"e2e-key-missing","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}