RocketChat/Rocket.Chat · warning · Meteor.Error

Custom_User_Status_Error_Invalid_User_Status

Custom_User_Status_Error_Invalid_User_Status

Error message

Invalid user status

What it means

`deleteCustomUserStatus` (exported helper used by the Meteor method and its REST counterpart) performs `CustomUserStatus.findOneAndDeleteById(userStatusID)` and throws `Custom_User_Status_Error_Invalid_User_Status` when the lookup-and-delete returns null — i.e. no custom user status exists with that id. Permission is checked first (`manage-user-status` → `not_authorized`), so reaching this error means you were authorized but the record was not found.

Source

Thrown at apps/meteor/server/meteor-methods/users/deleteCustomUserStatus.ts:23

import { hasPermissionAsync } from '../../lib/authorization/hasPermission';
import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		deleteCustomUserStatus(userStatusID: string): Promise<boolean>;
	}
}

export const deleteCustomUserStatus = async (userId: string, userStatusID: string): Promise<boolean> => {
	if (!(await hasPermissionAsync(userId, 'manage-user-status'))) {
		throw new Meteor.Error('not_authorized');
	}

	const userStatus = await CustomUserStatus.findOneAndDeleteById(userStatusID);
	if (userStatus == null) {
		throw new Meteor.Error('Custom_User_Status_Error_Invalid_User_Status', 'Invalid user status', { method: 'deleteCustomUserStatus' });
	}

	void api.broadcast('user.deleteCustomStatus', userStatus);

	return true;
};

Meteor.methods<ServerMethods>({
	async deleteCustomUserStatus(userStatusID) {
		methodDeprecationLogger.method('deleteCustomUserStatus', '9.0.0', '/v1/custom-user-status.delete');
		if (!this.userId) {
			throw new Meteor.Error('not_authorized');
		}

		return deleteCustomUserStatus(this.userId, userStatusID);
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Fetch the current list first (`GET /api/v1/custom-user-status.list`) and use ids from that response.
  2. Treat this error as idempotent success when the goal is 'make sure it is gone'.
  3. Refresh the admin UI list after every delete so stale ids are never reused.
  4. Confirm you are targeting the intended workspace/environment for the given id.
Defensive patterns

Strategy: validation

Validate before calling

// only delete ids that currently exist
const statuses = await (await fetch('/api/v1/custom-user-status.list', { headers: authHeaders })).json();
const exists = statuses.customUserStatuses.some(({ _id }) => _id === statusId);
if (exists) {
  await Meteor.callAsync('deleteCustomUserStatus', statusId);
}

Type guard

const isKnownStatusId = (id: string, known: string[]): boolean => known.includes(id);

Try / catch

try {
  await Meteor.callAsync('deleteCustomUserStatus', statusId);
} catch (e: any) {
  if (e?.error === 'Custom_User_Status_Error_Invalid_User_Status') {
    return; // already deleted - treat as success (idempotent)
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `deleteCustomUserStatus(userStatusID)` with an id that does not exist or was already deleted: double-submit of a delete button, stale list of statuses in the admin UI, or an id typo/wrong environment (e.g. dev id used against production).

Common situations: Race between two admins deleting the same status; front-end list not refreshed after a delete; sync scripts replaying deletions; ids copied between workspaces where the status was never created.

Related errors


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