RocketChat/Rocket.Chat · error · Error
Message not found
Error message
Message not found
What it means
Thrown by getMessageByID in the chats data layer when neither the local reactive store (Messages.state) nor the server fallback (GET /v1/chat.getMessage) returned a message for the given mid. findMessageByID first checks local state (excluding hidden messages) then queries the server; if both yield nothing, the message truly does not exist or is inaccessible.
Source
Thrown at apps/meteor/client/lib/chats/data.ts:45
_id: originalMessage?._id ?? Random.id(),
rid: effectiveRID,
...(effectiveTMID && {
tmid: effectiveTMID,
...(sendToChannel && { tshow: sendToChannel }),
}),
msg,
} as IMessage;
};
const findMessageByID = async (mid: IMessage['_id']): Promise<IMessage | null> =>
Messages.state.find((record) => record._id === mid && record._hidden !== true) ??
sdk.rest.get('/v1/chat.getMessage', { msgId: mid }).then((response) => mapMessageFromApi(response.message));
const getMessageByID = async (mid: IMessage['_id']): Promise<IMessage> => {
const message = await findMessageByID(mid);
if (!message) {
throw new Error('Message not found');
}
return message;
};
const findLastMessage = async (): Promise<IMessage | undefined> =>
Messages.state.findFirst(
(record) => record.rid === rid && (tmid ? record.tmid === tmid : !record.tmid) && record._hidden !== true,
(a, b) => b.ts.getTime() - a.ts.getTime(),
);
const getLastMessage = async (): Promise<IMessage> => {
const message = await findLastMessage();
if (!message) {
throw new Error('Message not found');
}
View on GitHub (pinned to f9d3ec372b)
Solutions
- Verify the mid is correct and not truncated (deep links/notifications can mangle ids).
- Confirm the user has read access to the room the message belongs to.
- Handle the thrown error to show a 'message no longer available' state instead of crashing.
- If the message was deleted, refresh the thread/room list to reflect the new state.
- For hidden messages, ensure the caller expects a hidden message to be treated as absent.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify read access before lookup
if (!hasAtLeastOnePermission('read-message', roomId)) {
throw new Error('No read access');
} Type guard
function isFoundMessage(m: IMessage | null | undefined): m is IMessage {
return m != null;
} Try / catch
try {
const msg = await getMessageByID(mid);
} catch (e) {
if ((e as Error).message === 'Message not found') {
showMessageUnavailable();
}
} Prevention
- Validate the mid is complete and not truncated from a deep link.
- Confirm the user has read access to the message's room.
- Handle the error to show a 'message unavailable' state instead of crashing.
When it happens
Trigger: Calling getMessageByID(mid) where mid does not exist, was deleted, belongs to a room the user cannot read, or the server returned no message in the chat.getMessage response (response.message falsy). The local lookup also filters out _hidden === true records, so a hidden message in local state still falls through to the server.
Common situations: Stale message id from an old notification/deep link; the message was deleted between fetch and access; the user lacks 'read-message'/'preview-room' permission for the room; the room is a private channel the user was removed from; a deep link with a truncated/typo'd id.
Related errors
- Invalid token for livechat message
- Invalid editor assigned to the message for the update.
- Invalid message id
- Invalid username
- Unrecognized typing scope provided
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/642194e719ba549f.
Report an issue: GitHub.