RocketChat/Rocket.Chat · error · Error

invalid-message

Error message

invalid-message

What it means

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.

Solutions

  1. Verify the message id against GET /api/v1/livechat/messages.history/:rid?token=... to confirm it is still present in that room.
  2. Treat this error as a 404-equivalent in the UI: drop the local reference to the deleted message instead of retrying.
  3. If it should exist, check you are querying the same server/replica where it was sent (rare cross-instance mismatch).
  4. 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.

Example fix

// before
const res = await fetch(`/api/v1/livechat/message/${msgId}?token=${token}&rid=${rid}`);
const body = await res.json();
if (!body.success) throw new Error('unexpected failure');

// after (distinguish not-found from other failures)
if (body.error === 'invalid-message') {
  removeMessageFromLocalState(msgId); // message was deleted, stop referencing it
} else {
  throw new Error(`livechat message fetch failed: ${body.error}`);
}
Defensive patterns

Strategy: fallback

Validate before calling

// Confirm the message still exists in the room before deep-linking to it
async function messageExists(token: string, rid: string, msgId: string): Promise<boolean> {
  const res = await fetch(`/api/v1/livechat/messages.history/${rid}?token=${encodeURIComponent(token)}&limit=50`);
  const body = await res.json();
  return body.success && body.messages.some((m: { _id: string }) => m._id === msgId);
}

Try / catch

if (isLivechatErrorResponse(body) && body.error === 'invalid-message') {
  removeMessageFromLocalState(msgId); // treat as deleted; do not retry
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/08f419c4bf1726f1. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/server/api/v1/omnichannel/message.ts:104

	{ validateParams: { GET: isGETLivechatMessageIdParams, PUT: isPUTLivechatMessageIdParams, DELETE: isDELETELivechatMessageIdParams } },
	{
		async get() {
			const { token, rid } = this.queryParams;
			const { _id } = this.urlParams;

			const guest = await findGuest(token);
			if (!guest) {
				throw new Error('invalid-token');
			}

			const room = await findRoom(token, rid);
			if (!room) {
				throw new Error('invalid-room');
			}

			let message = await Messages.findOneByRoomIdAndMessageId(rid, _id);
			if (!message) {
				throw new Error('invalid-message');
			}

			if (message.file) {
				message = { ...(await normalizeMessageFileUpload(message)), ...{ _updatedAt: message._updatedAt } };
			}

			if (!message) {
				throw new Error('invalid-message');
			}

			return API.v1.success({ message });
		},

		async put() {
			const { token, rid } = this.bodyParams;
			const { _id } = this.urlParams;

			const guest = await findGuest(token);

View on GitHub (pinned to b2c16d5842)