RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

updateMessage resolved the DDP connection's user id but Users.findOneById(uid) returned null — the user document no longer exists. The authenticated session points at a deleted (or missing) account, so the edit cannot proceed. This signals account/session inconsistency rather than a bad request.

Source

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

		let currentTsDiff = 0;
		let msgTs;

		if (originalMessage.ts instanceof Date || Match.test(originalMessage.ts, Number)) {
			msgTs = moment(originalMessage.ts);
		}
		if (msgTs) {
			currentTsDiff = moment().diff(msgTs, 'minutes');
		}
		if (currentTsDiff >= blockEditInMinutes) {
			throw new Meteor.Error('error-message-editing-blocked', 'Message editing is blocked', {
				method: 'updateMessage',
			});
		}
	}

	const user = await Users.findOneById(uid);
	if (!user) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'updateMessage' });
	}
	await canSendMessageAsync(message.rid, { uid: user._id, username: user.username ?? undefined, ...user });

	// It is possible to have an empty array as the attachments property, so ensure both things exist
	if (originalMessage.attachments && originalMessage.attachments.length > 0 && originalMessage.attachments[0].description !== undefined) {
		originalMessage.attachments[0].description = message.msg;
		message.attachments = originalMessage.attachments;
		message.msg = originalMessage.msg;
	}

	message.u = originalMessage.u;

	return updateMessage(message, user, originalMessage, previewUrls);
}

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Log the affected client out and re-authenticate — a fresh session resolves to a valid identity or fails cleanly at login
  2. Verify the account still exists via Admin > Users or the users.info REST endpoint for that uid
  3. If deletion is intended, invalidate that user's sessions/tokens on deletion; if accidental, restore the account from backup

Example fix

// before
await Meteor.callAsync('updateMessage', payload); // throws for a deleted user's session

// after
try {
  await Meteor.callAsync('updateMessage', payload);
} catch (e) {
  if (isMeteorErrorCode(e, 'error-invalid-user')) {
    await Meteor.logout(); // drop the stale session and send the user to login
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

const me = await fetch('/api/v1/me', { headers: authHeaders() });
if (me.status === 401 || me.status === 400) {
  forceRelogin(); // session points at a missing/invalid user
}

Type guard

const isInvalidUserError = (e: unknown): e is Meteor.Error =>
  typeof e === 'object' && e !== null && (e as { error?: string }).error === 'error-invalid-user';

Try / catch

try {
  await Meteor.callAsync('updateMessage', payload);
} catch (e) {
  if (isInvalidUserError(e) && Meteor.userId()) {
    // session exists but the user document is gone — only recovery is re-login
    await Meteor.logout();
    redirectToLogin();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The user was deleted (admin purge, deletion workflow) while their DDP session or login token was still valid; the user record removed directly from the database; data inconsistency after a partial import or restore.

Common situations: Admin deletes a user whose client is still connected; automated cleanup purges accounts with live sessions; staging environments copied without the users collection.

Related errors


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