{"record":{"id":"08f419c4bf1726f1","repo":"RocketChat/Rocket.Chat","slug":"invalid-message","errorCode":null,"errorMessage":"invalid-message","messagePattern":"invalid-message","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/message.ts","lineNumber":104,"sourceCode":"\t{ validateParams: { GET: isGETLivechatMessageIdParams, PUT: isPUTLivechatMessageIdParams, DELETE: isDELETELivechatMessageIdParams } },\n\t{\n\t\tasync get() {\n\t\t\tconst { token, rid } = this.queryParams;\n\t\t\tconst { _id } = this.urlParams;\n\n\t\t\tconst guest = await findGuest(token);\n\t\t\tif (!guest) {\n\t\t\t\tthrow new Error('invalid-token');\n\t\t\t}\n\n\t\t\tconst room = await findRoom(token, rid);\n\t\t\tif (!room) {\n\t\t\t\tthrow new Error('invalid-room');\n\t\t\t}\n\n\t\t\tlet message = await Messages.findOneByRoomIdAndMessageId(rid, _id);\n\t\t\tif (!message) {\n\t\t\t\tthrow new Error('invalid-message');\n\t\t\t}\n\n\t\t\tif (message.file) {\n\t\t\t\tmessage = { ...(await normalizeMessageFileUpload(message)), ...{ _updatedAt: message._updatedAt } };\n\t\t\t}\n\n\t\t\tif (!message) {\n\t\t\t\tthrow new Error('invalid-message');\n\t\t\t}\n\n\t\t\treturn API.v1.success({ message });\n\t\t},\n\n\t\tasync put() {\n\t\t\tconst { token, rid } = this.bodyParams;\n\t\t\tconst { _id } = this.urlParams;\n\n\t\t\tconst guest = await findGuest(token);","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/omnichannel/message.ts#L86-L122","documentation":"Thrown by GET /api/v1/livechat/message/:_id when Messages.findOneByRoomIdAndMessageId(rid, _id) returns null. The lookup is scoped to both the room id and the message id, so the error means no message document exists with that _id inside that rid. Token and room have already been validated at this point, so the problem is purely the message identifier or its persistence.","triggerScenarios":"GET /api/v1/livechat/message/<msgId> where msgId is wrong, the message was deleted (e.g. via DELETE livechat/message/:_id in another tab), or the message exists but belongs to a different room than the rid supplied.","commonSituations":"UI tries to render a message referenced in a notification/preview after the agent deleted it; client caches message ids across conversation resets; typos or truncation of the 17-char message _id; using the rid as the message _id in the URL path.","solutions":["Verify the message id against GET /api/v1/livechat/messages.history/:rid?token=... to confirm it is still present in that room.","Treat this error as a 404-equivalent in the UI: drop the local reference to the deleted message instead of retrying.","If it should exist, check you are querying the same server/replica where it was sent (rare cross-instance mismatch).","Make sure the _id in the URL path is the message id and rid in the query string is the room id — swapping them produces exactly this error."],"exampleFix":"// before\nconst res = await fetch(`/api/v1/livechat/message/${msgId}?token=${token}&rid=${rid}`);\nconst body = await res.json();\nif (!body.success) throw new Error('unexpected failure');\n\n// after (distinguish not-found from other failures)\nif (body.error === 'invalid-message') {\n  removeMessageFromLocalState(msgId); // message was deleted, stop referencing it\n} else {\n  throw new Error(`livechat message fetch failed: ${body.error}`);\n}","handlingStrategy":"fallback","validationCode":"// Confirm the message still exists in the room before deep-linking to it\nasync function messageExists(token: string, rid: string, msgId: string): Promise<boolean> {\n  const res = await fetch(`/api/v1/livechat/messages.history/${rid}?token=${encodeURIComponent(token)}&limit=50`);\n  const body = await res.json();\n  return body.success && body.messages.some((m: { _id: string }) => m._id === msgId);\n}","typeGuard":null,"tryCatchPattern":"if (isLivechatErrorResponse(body) && body.error === 'invalid-message') {\n  removeMessageFromLocalState(msgId); // treat as deleted; do not retry\n}","preventionTips":["Treat 'invalid-message' as a 404: purge the local reference instead of retrying the request.","Before rendering a message from a push notification/preview, verify it against room history.","Expect concurrent deletes (agent or other tab) and design the message store to tolerate removals."],"tags":["livechat","omnichannel","message-not-found","rest-api"],"backgroundTag":"resource-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}