RocketChat/Rocket.Chat · error · Meteor.Error

error-not-allowed

error-not-allowed

Error message

Not allowed

What it means

The `deleteUser` Meteor method throws `error-not-allowed` when `Meteor.userId()` is null — there is no authenticated DDP session. This is the first gate in the method wrapper, before the `delete-user` permission check and before `executeDeleteUser` runs. The method is deprecated since 9.0.0 in favor of REST `DELETE /v1/users.delete`.

Source

Thrown at apps/meteor/server/meteor-methods/users/deleteUser.ts:55

		throw new Meteor.Error('error-action-not-allowed', 'Leaving the app without admins is not allowed', {
			method: 'deleteUser',
			action: 'Remove_last_admin',
		});
	}

	await deleteUser(userId, confirmRelinquish, fromUserId);

	return true;
};

Meteor.methods<ServerMethods>({
	async deleteUser(userId, confirmRelinquish = false) {
		methodDeprecationLogger.method('deleteUser', '9.0.0', '/v1/users.delete');
		check(userId, String);

		const uid = Meteor.userId();
		if (!uid) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', {
				method: 'deleteUser',
			});
		}

		if ((await hasPermissionAsync(uid, 'delete-user')) !== true) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', {
				method: 'deleteUser',
			});
		}

		return executeDeleteUser(uid, userId, confirmRelinquish);
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Authenticate first; only call `deleteUser` when `Meteor.userId()` is set.
  2. Prefer the REST endpoint `DELETE /api/v1/users.delete` with an auth token + `delete-user` permission.
  3. Re-run the login flow on reconnect and retry.
Defensive patterns

Strategy: validation

Validate before calling

if (!Meteor.userId()) {
  return; // require an authenticated session before deleting users
}
await Meteor.callAsync('deleteUser', userId, confirmRelinquish);

Type guard

const isAuthenticated = (): boolean => typeof Meteor.userId() === 'string';

Try / catch

try {
  await Meteor.callAsync('deleteUser', userId);
} catch (e: any) {
  if (e?.error === 'error-not-allowed' && !Meteor.userId()) {
    // first gate: no session. Re-authenticate and retry.
  }
}

Prevention

When it happens

Trigger: Calling `Meteor.call('deleteUser', userId, confirmRelinquish?)` while unauthenticated: logged-out tab, expired resume token after reconnect, or server-side invocation without a user context.

Common situations: Admin UI actions fired from stale sessions; scripts calling the deprecated DDP method without login; token invalidation during long-running sessions.

Related errors


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