RocketChat/Rocket.Chat · error · Error

error-invalid-message_id

error-invalid-message_id

Error message

error-invalid-message_id

What it means

Thrown by reportMessage (Rocket.Chat moderation reporting) when Messages.findOneById(messageId) returns null, i.e. no message document matches the supplied ID. The server treats a nonexistent target message as invalid input rather than a permission problem. Most often the message was deleted before the report was submitted, or the caller passed a room ID (rid) instead of the message _id.

Source

Thrown at apps/meteor/server/lib/moderation/reportMessage.ts:19

import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage, IUser } from '@rocket.chat/core-typings';
import { Messages, ModerationReports, Rooms, Users } from '@rocket.chat/models';

import { canAccessRoomAsync } from '../authorization/canAccessRoom';

export const reportMessage = async (messageId: IMessage['_id'], description: string, uid: IUser['_id']) => {
	if (!uid) {
		throw new Error('error-invalid-user');
	}

	if (!description.trim()) {
		throw new Error('error-invalid-description');
	}

	const message = await Messages.findOneById(messageId);

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

	const user = await Users.findOneById(uid);

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

	const { rid } = message;
	// If the user can't access the room where the message is, report that the message id is invalid
	const room = await Rooms.findOneById(rid);
	if (!room || !(await canAccessRoomAsync(room, { _id: uid }))) {
		throw new Error('error-invalid-message_id');
	}

	const reportedBy = {
		_id: user._id,
		username: user.username,

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Confirm you are passing the message _id, not the room rid or another field
  2. Re-fetch the message right before reporting to confirm it still exists
  3. In the UI, treat this error as 'message no longer exists' instead of offering a retry
  4. In tests, seed the Messages collection before invoking reportMessage

Example fix

// before
await reportMessage(rid, description, uid); // room id passed by mistake

// after
await reportMessage(message._id, description, Meteor.userId());
Defensive patterns

Strategy: validation

Validate before calling

const message = await Messages.findOneById(messageId, { projection: { _id: 1, rid: 1 } });
if (!message) {
  // do not call reportMessage; the target no longer exists
  throw new Error('message not found');
}

Try / catch

try {
  await reportMessage(messageId, description, uid);
} catch (err) {
  if (err instanceof Error && err.message === 'error-invalid-message_id') {
    // treat as 'message deleted or not visible' - do not retry blindly
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the moderation report flow (reportMessage server lib / moderation.report API) with a messageId that was deleted, an ID copied from the wrong field (rid instead of message _id), or a fabricated ID in tests where the Messages collection was never seeded.

Common situations: Report dialog left open while the message gets deleted; moderation bots acting on stale IDs; test fixtures that create rooms/users but no messages; passing undefined or an object as messageId.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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