RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

There is no user with this username

What it means

Thrown by the POST roles.removeUserFromRole REST endpoint when Users.findOneByUsername(username) returns null, meaning no user document matches the username sent in the request body. The endpoint validates the user before it resolves the role, so a missing or mistyped username fails fast with HTTP 400 and errorType 'error-invalid-user'. The lookup is strictly by username, not by user _id.

Solutions

  1. Verify the username first with GET /api/v1/users.info?username=<username> and only call removeUserFromRole when it returns a user
  2. Send the account's username in the username body field, not the _id (fetch it from users.info if you only have an ID)
  3. Trim whitespace and match username casing exactly against the stored user record
  4. If the user was deleted, treat the role removal as unnecessary and skip the call instead of retrying

Example fix

// before
await sdk.post('roles.removeUserFromRole', { roleId: 'moderator', username: 'usr_8f3c2b' }); // _id passed as username -> error-invalid-user

// after
const { user } = await sdk.get('users.info', { username });
if (!user?.username) throw new Error(`no user '${username}'`);
await sdk.post('roles.removeUserFromRole', { roleId: 'moderator', username: user.username });
Defensive patterns

Strategy: validation

Validate before calling

const { user } = await sdk.get('users.info', { username });
if (!user?.username) throw new Error(`no user '${username}' — aborting role removal`);

Try / catch

try {
  await sdk.post('roles.removeUserFromRole', { roleId, username });
} catch (e: any) {
  if (e?.response?.data?.errorType === 'error-invalid-user') {
    // user missing: verify username or treat as no-op
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/v1/roles.removeUserFromRole with body { roleId, username } where username is a typo, belongs to a deleted user, or the caller mistakenly sent the user's _id instead of the username. Omitting the username field entirely also produces this error because findOneByUsername(undefined) resolves nothing.

Common situations: Automation scripts that store user IDs and send them as the username; users renamed or deleted between the initial fetch and the role call; provisioning imports where usernames differ from the source system; case mismatches or trailing whitespace, since the username match is exact.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at apps/meteor/server/api/v1/roles.ts:287

				}),
				400: validateBadRequestErrorResponse,
				401: validateUnauthorizedErrorResponse,
				403: validateForbiddenErrorResponse,
			},
		},
		async function action() {
			const { bodyParams } = this;

			const { roleId, username, scope } = bodyParams;

			if (!roleId) {
				return API.v1.failure('error-invalid-role-properties');
			}

			const user = await Users.findOneByUsername(username);

			if (!user) {
				throw new Meteor.Error('error-invalid-user', 'There is no user with this username');
			}

			const role = await Roles.findOneById(roleId);

			if (!role) {
				throw new Meteor.Error('error-invalid-roleId', 'This role does not exist');
			}

			if (!(await hasAnyRoleAsync(user._id, [role._id], scope))) {
				throw new Meteor.Error('error-user-not-in-role', 'User is not in this role');
			}

			if (role._id === 'admin') {
				const adminCount = await Roles.countUsersInRole('admin');
				if (adminCount === 1) {
					throw new Meteor.Error('error-admin-required', 'You need to have at least one admin');
				}
			}

View on GitHub (pinned to b2c16d5842)