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
- Confirm you are passing the message _id, not the room rid or another field
- Re-fetch the message right before reporting to confirm it still exists
- In the UI, treat this error as 'message no longer exists' instead of offering a retry
- 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
- Report from freshly rendered message state, not long-cached lists
- Always pass the message _id, never the rid
- Seed messages in test fixtures before exercising the report flow
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
- Not allowed
- The required "roomId" or "roomName" param provided does not
- User not found
- User is not in this room
- User is already banned from this room
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/4c62ba021e505509.
Report an issue: GitHub.