{"record":{"id":"eacba7e16ed47e6d","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-message-eacba7","errorCode":"error-invalid-message","errorMessage":"Invalid message","messagePattern":"Invalid message","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/messages/deleteMessage.ts","lineNumber":15,"sourceCode":"import { AppEvents, Apps } from '@rocket.chat/apps';\nimport { api, Message } from '@rocket.chat/core-services';\nimport { isThreadMessage, type AtLeast, type IMessage, type IRoom, type IThreadMessage, type IUser } from '@rocket.chat/core-typings';\nimport { Messages, Rooms, Uploads, Users, ReadReceipts, ReadReceiptsArchive, Subscriptions } from '@rocket.chat/models';\nimport { Meteor } from 'meteor/meteor';\n\nimport { settings } from '../../settings';\nimport { canDeleteMessageAsync } from '../authorization/canDeleteMessage';\nimport { callbacks } from '../callbacks';\nimport { FileUpload } from '../media/file-upload';\nimport { notifyOnRoomChangedById, notifyOnMessageChange, notifyOnSubscriptionChangedByRoomIdAndUserIds } from '../notifyListener';\n\nexport const deleteMessageValidatingPermission = async (message: AtLeast<IMessage, '_id'>, userId: IUser['_id']): Promise<void> => {\n\tif (!message?._id) {\n\t\tthrow new Meteor.Error('error-invalid-message', 'Invalid message');\n\t}\n\tif (!userId) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user');\n\t}\n\n\tconst user = await Users.findOneById(userId);\n\tconst originalMessage = await Messages.findOneById(message._id);\n\n\tif (!originalMessage || !user || !(await canDeleteMessageAsync(user, originalMessage))) {\n\t\tthrow new Meteor.Error('error-action-not-allowed', 'Not allowed');\n\t}\n\n\treturn deleteMessage(originalMessage, user);\n};\n\nexport async function deleteMessage(message: IMessage, user: IUser): Promise<void> {\n\tconst deletedMsg: IMessage | null = await Messages.findOneById(message._id);\n\tconst isThread = (deletedMsg?.tcount || 0) > 0;","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/messages/deleteMessage.ts#L1-L33","documentation":"deleteMessageValidatingPermission (apps/meteor/server/lib/messages/deleteMessage.ts:13-16) is the entry point behind the deleteMessage DDP method and the chat.delete REST call. It requires a truthy message._id before doing anything else; a message object without one throws error-invalid-message 'Invalid message'. This is an input-shape check that runs before any permission lookup.","triggerScenarios":"Calling Meteor.call('deleteMessage', {}) or chat.delete with a body missing the messageId/_id field; passing a message stub built from a template/event payload that never had an id set; destructuring bugs that send { msg } instead of { _id }.","commonSituations":"Custom UI code calling the deletion method with the wrong object shape; integrations reacting to webhooks and deleting with an undefined id; race where the caller deletes based on a message that was never sent so no id exists.","solutions":["Pass the _id of an existing message: Meteor.call('deleteMessage', { _id }) or POST chat.delete with { roomId, msgId }","Validate the payload shape before invoking the API (assert _id is a non-empty string)","Log the offending payload when this fires - it almost always indicates a caller bug, not a server problem"],"exampleFix":"// before\nMeteor.call('deleteMessage', { msg: message.msg }); // -> error-invalid-message\n// after\nMeteor.call('deleteMessage', { _id: message._id });","handlingStrategy":"validation","validationCode":"if (typeof message?._id !== 'string' || message._id.length === 0) {\n  throw new TypeError('deleteMessage requires message._id');\n}\nawait deleteMessageValidatingPermission(message, userId);","typeGuard":"const hasMessageId = (m: unknown): m is { _id: string } =>\n  typeof m === 'object' && m !== null && typeof (m as any)._id === 'string' && (m as any)._id.length > 0;","tryCatchPattern":"try {\n  await deleteMessageValidatingPermission(message, userId);\n} catch (error: any) {\n  if (error instanceof Meteor.Error && error.error === 'error-invalid-message') {\n    // caller bug: payload lacks _id; fix the caller, do not retry\n    logPayloadShapeError(message);\n    return;\n  }\n  throw error;\n}","preventionTips":["Always pass {_id} from the message document you render","Type your call sites against AtLeast<IMessage, '_id'>","Assert payload shape at integration boundaries"],"tags":["messages","delete","input-validation","meteor-method"],"backgroundTag":"invalid-message-reference","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}