RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

In dry-run mode Mailer.sendMail looks up the account whose email equals 'from' (Users.findOneByEmailAddress) to render one sample message; if no user matches it throws error-invalid-user. The dry-run therefore requires the from-address to belong to an existing local user account.

Source

Thrown at apps/meteor/server/lib/notifications/mail-messages/functions/sendMail.ts:43

}): Promise<void> {
	Mailer.checkAddressFormatAndThrow(from, 'Mailer.sendMail');

	if (body.indexOf('[unsubscribe]') === -1) {
		throw new Meteor.Error('error-missing-unsubscribe-link', 'You must provide the [unsubscribe] link.', {
			function: 'Mailer.sendMail',
		});
	}

	let userQuery: Filter<any> = { 'mailer.unsubscribed': { $exists: 0 } };
	if (query) {
		userQuery = { $and: [userQuery, EJSON.parse(query)] };
	}

	if (dryrun) {
		const user = await Users.findOneByEmailAddress(from);

		if (!user) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				function: 'Mailer.sendMail',
			});
		}

		const email = `${user.name} <${user.emails?.[0].address}>`;
		const html = placeholders.replace(body, {
			unsubscribe: Meteor.absoluteUrl(
				generatePath('mailer/unsubscribe/:_id/:createdAt', {
					_id: user._id,
					createdAt: user.createdAt?.getTime().toString() || '',
				}),
			),
			name: user.name,
			email,
		});

		SystemLogger.debug({
			msg: 'Sending email',

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Set 'from' to the email of an existing user (typically your admin account) when using dryrun: true
  2. Verify first with Users.findOneByEmailAddress(from)
  3. Alternatively drop dryrun and constrain recipients with a narrow 'query' instead

Example fix

// before
await Mailer.sendMail({ from: 'noreply@external.com', subject, body, dryrun: true });

// after
const admin = await Users.findOneByEmailAddress('admin@yourdomain.tld');
if (!admin) throw new Error('pick a from address owned by a real user');
await Mailer.sendMail({ from: admin.emails[0].address, subject, body, dryrun: true });
Defensive patterns

Strategy: validation

Validate before calling

const user = await Users.findOneByEmailAddress(from);
if (!user) {
  // dryrun needs a from address owned by an existing user
  throw new Error('from address has no matching user');
}
await Mailer.sendMail({ from, subject, body, dryrun: true });

Try / catch

try {
  await Mailer.sendMail({ from, subject, body, dryrun: true });
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'error-invalid-user') {
    // switch 'from' to an address belonging to a real user and retry the dry run
  } else throw err;
}

Prevention

When it happens

Trigger: Mailer.sendMail({ from: 'marketing@external.com', dryrun: true, ... }) where the address is not attached to any Rocket.Chat user; the matching user was deleted; a typo or case mismatch against the stored email.

Common situations: Testing the Mailer with an external or no-reply address; organization changed its from-address without a matching user account; admin testing after user cleanup.

Related errors


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