{"record":{"id":"daf05f6cd9bb307b","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-message-daf05f","errorCode":"error-invalid-message","errorMessage":"Invalid message","messagePattern":"Invalid message","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/messages/unfollowMessage.ts","lineNumber":29,"sourceCode":"import { unfollow } from '../../lib/messaging/threads/functions';\nimport { notifyOnMessageChange } from '../../lib/notifyListener';\nimport { settings } from '../../settings';\n\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tunfollowMessage(message: { mid: IMessage['_id'] }): false | undefined;\n\t}\n}\n\nexport const unfollowMessage = async (user: IUser, { mid }: { mid: IMessage['_id'] }): Promise<false | undefined> => {\n\tif (mid && !settings.get('Threads_enabled')) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'unfollowMessage' });\n\t}\n\n\tconst message = await Messages.findOneById(mid);\n\tif (!message) {\n\t\tthrow new Meteor.Error('error-invalid-message', 'Invalid message', {\n\t\t\tmethod: 'unfollowMessage',\n\t\t});\n\t}\n\n\tif (!(await canAccessRoomIdAsync(message.rid, user._id))) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'unfollowMessage' });\n\t}\n\n\tconst id = message.tmid || message._id;\n\n\tconst unfollowResult = await unfollow({ rid: message.rid, tmid: id, uid: user._id });\n\n\tvoid notifyOnMessageChange({\n\t\tid,\n\t});\n\n\tconst isFollowed = false;\n\tawait Apps.self?.triggerEvent(AppEvents.IPostMessageFollowed, message, user, isFollowed);","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/messages/unfollowMessage.ts#L11-L47","documentation":"unfollowMessage loads the target with Messages.findOneById(mid); a null result throws error-invalid-message. The id is unknown: the message was deleted, never existed, or came from a different workspace. There is no authorization involved yet at this point.","triggerScenarios":"Message deleted or purged by retention while its thread was still open in the client; passing a malformed or wrong mid; ids from a pre-restore database snapshot.","commonSituations":"Retention jobs purging old thread parents; moderator deletes while users view the thread; cache pointing at messages that no longer exist.","solutions":["Treat as stale state: clear the local follow indicator, do not retry","Verify the message/thread still exists before offering the unfollow action","Refresh thread data after deletions or retention purges"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tawait Meteor.callAsync('unfollowMessage', { mid });\n} catch (e: any) {\n\tif (e?.error === 'error-invalid-message') {\n\t\t// message gone: clear local follow state, treat as success (idempotent)\n\t\tmarkNotFollowed(mid);\n\t\treturn;\n\t}\n\tthrow e;\n}","preventionTips":["Treat unfollow as idempotent cleanup - a missing target is success, not failure","Drop cached message ids when the owning thread/room is pruned","Verify mid format before calling; non-string ids fail check(mid, String) earlier"],"tags":["meteor-method","threads","messages","data-integrity"],"backgroundTag":"message-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}