RocketChat/Rocket.Chat · error · Meteor.Error

error-message-same-as-tmid

error-message-same-as-tmid

Error message

Cannot set tmid the same as the _id

What it means

Thrown by Rocket.Chat's updateMessage Meteor method when an edit payload sets tmid (the thread parent id) to the message's own _id. The server compares the stored message's _id with the incoming tmid and rejects a self-referencing thread reference, because a message cannot be its own thread parent. This is a request-validation guard, not a server fault.

Source

Thrown at apps/meteor/server/meteor-methods/messages/updateMessage.ts:43

	Object.entries(message).forEach(([key, value]) => {
		if (!allowedEditedFields.includes(key) && value !== originalMessage[key as keyof IMessage]) {
			throw new Meteor.Error('error-invalid-update-key', `Cannot update the message ${key}`, {
				method: 'updateMessage',
			});
		}
	});

	// IF the message has custom fields, always update
	// Ideally, we'll compare the custom fields to check for change, but since we don't know the shape of
	// custom fields, as it's user defined, we're gonna update
	const msgText = originalMessage?.attachments?.[0]?.description ?? originalMessage.msg;
	if (msgText === message.msg && !previewUrls && !message.customFields) {
		return;
	}

	if (!!message.tmid && originalMessage._id === message.tmid) {
		throw new Meteor.Error('error-message-same-as-tmid', 'Cannot set tmid the same as the _id', {
			method: 'updateMessage',
		});
	}

	if (!originalMessage.tmid && !!message.tmid) {
		throw new Meteor.Error('error-message-change-to-thread', 'Cannot update message to a thread', { method: 'updateMessage' });
	}

	const _hasPermission = await hasPermissionAsync(uid, 'edit-message', message.rid);
	const editAllowed = settings.get('Message_AllowEditing');
	const editOwn = originalMessage.u && originalMessage.u._id === uid;

	if (!_hasPermission && (!editAllowed || !editOwn)) {
		throw new Meteor.Error('error-action-not-allowed', 'Message editing not allowed', {
			method: 'updateMessage',
			action: 'Message_editing',
		});
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Remove tmid from the edit payload — the server preserves the message's existing threading; only send fields you intend to change (msg, attachments, customFields)
  2. If the goal is to reply inside a thread, send a new message with tmid set to the parent message's _id instead of editing
  3. Audit payload construction so tmid always references the parent message and never the edited message's own _id

Example fix

// before
Meteor.call('updateMessage', { ...msg, tmid: msg._id }); // self reference

// after
const { tmid, ...changes } = msg;
Meteor.call('updateMessage', { _id: msg._id, ...changes }); // no tmid on edit
Defensive patterns

Strategy: validation

Validate before calling

const tmidIsValid = (payload: { _id: string; tmid?: string }): boolean =>
  !payload.tmid || payload.tmid !== payload._id;
if (!tmidIsValid(editPayload)) {
  throw new Error('refusing to submit: tmid equals _id');
}

Type guard

const isSameTmidError = (e: unknown): e is Meteor.Error =>
  typeof e === 'object' && e !== null && (e as { error?: string }).error === 'error-message-same-as-tmid';

Try / catch

try {
  await Meteor.callAsync('updateMessage', payload);
} catch (e) {
  if (isSameTmidError(e)) {
    const { tmid, ...rest } = payload;
    return Meteor.callAsync('updateMessage', rest); // retry once without tmid
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling Meteor.call('updateMessage', message) with message.tmid truthy and equal to the _id of the message being edited. Typically the payload is built by spreading an existing message object and tmid gets assigned from the wrong variable (the message's own _id instead of its parent's _id).

Common situations: Custom clients or Apps-Engine code that reuses a fetched message object as the edit payload; thread UIs mixing up the current message id and the parent message id; bots or migration scripts replaying edits with reconstructed payloads.

Related errors


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