RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-message
error-invalid-message
Error message
Invalid message
What it means
unfollowMessage loads the target with Messages.findOneById(mid); a null result throws error-invalid-message. The id is unknown: the message was deleted, never existed, or came from a different workspace. There is no authorization involved yet at this point.
Source
Thrown at apps/meteor/server/meteor-methods/messages/unfollowMessage.ts:29
import { unfollow } from '../../lib/messaging/threads/functions';
import { notifyOnMessageChange } from '../../lib/notifyListener';
import { settings } from '../../settings';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unfollowMessage(message: { mid: IMessage['_id'] }): false | undefined;
}
}
export const unfollowMessage = async (user: IUser, { mid }: { mid: IMessage['_id'] }): Promise<false | undefined> => {
if (mid && !settings.get('Threads_enabled')) {
throw new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'unfollowMessage' });
}
const message = await Messages.findOneById(mid);
if (!message) {
throw new Meteor.Error('error-invalid-message', 'Invalid message', {
method: 'unfollowMessage',
});
}
if (!(await canAccessRoomIdAsync(message.rid, user._id))) {
throw new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'unfollowMessage' });
}
const id = message.tmid || message._id;
const unfollowResult = await unfollow({ rid: message.rid, tmid: id, uid: user._id });
void notifyOnMessageChange({
id,
});
const isFollowed = false;
await Apps.self?.triggerEvent(AppEvents.IPostMessageFollowed, message, user, isFollowed);View on GitHub (pinned to b2c16d5842)
Solutions
- Treat as stale state: clear the local follow indicator, do not retry
- Verify the message/thread still exists before offering the unfollow action
- Refresh thread data after deletions or retention purges
Defensive patterns
Strategy: try-catch
Try / catch
try {
await Meteor.callAsync('unfollowMessage', { mid });
} catch (e: any) {
if (e?.error === 'error-invalid-message') {
// message gone: clear local follow state, treat as success (idempotent)
markNotFollowed(mid);
return;
}
throw e;
} Prevention
- Treat unfollow as idempotent cleanup - a missing target is success, not failure
- Drop cached message ids when the owning thread/room is pruned
- Verify mid format before calling; non-string ids fail check(mid, String) earlier
When it happens
Trigger: Message deleted or purged by retention while its thread was still open in the client; passing a malformed or wrong mid; ids from a pre-restore database snapshot.
Common situations: Retention jobs purging old thread parents; moderator deletes while users view the thread; cache pointing at messages that no longer exist.
Related errors
- error-room-does-not-exist
- invalid-params
- error-not-allowed
- error-room-does-not-exist
- error-invalid-message
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/daf05f6cd9bb307b.
Report an issue: GitHub.