RocketChat/Rocket.Chat · error · Meteor.Error

error-updating-custom-user-status

error-updating-custom-user-status

Error message

Error updating custom user status

What it means

Thrown by POST custom-user-status.update as a post-condition check: the endpoint first returns an explicit failure if no status with the given _id exists, then runs insertOrUpdateUserStatus and re-reads the record by _id; if that read comes back empty it throws Meteor.Error('error-updating-custom-user-status'). This means the update path itself dropped or renamed the record — typically the body changed the name to one that collides with another existing status.

Solutions

  1. Confirm the target _id still exists via custom-user-status.list before updating.
  2. When renaming, verify the new name is not already taken (case-insensitive) by another status.
  3. Re-fetch the list on this error and reconcile your local cache instead of blind-retrying.

Example fix

// before
await api.post('custom-user-status.update', { _id, name: newName, statusType });

// after — ensure the new name is free before renaming
const { statuses } = await api.get('custom-user-status.list');
const taken = statuses.some(s => s._id !== _id && s.name.toLowerCase() === newName.trim().toLowerCase());
if (!taken) await api.post('custom-user-status.update', { _id, name: newName.trim(), statusType });
Defensive patterns

Strategy: validation

Validate before calling

async function safeUpdateStatus(api, _id: string, name: string, statusType: string) {
  const { statuses } = await api.get('custom-user-status.list');
  const exists = statuses.some(s => s._id === _id);
  const nameTaken = statuses.some(s => s._id !== _id && s.name.toLowerCase() === name.trim().toLowerCase());
  if (exists && !nameTaken) await api.post('custom-user-status.update', { _id, name: name.trim(), statusType });
}

Try / catch

try { await api.post('custom-user-status.update', { _id, name, statusType }); }
catch (e) {
  if (e.error === 'error-updating-custom-user-status') { await refreshStatuses(); /* reconcile cache */ } else throw e;
}

Prevention

When it happens

Trigger: POSTing custom-user-status.update with { _id, name } where name collides (case-insensitively) with a different existing status so the underlying update silently does not apply, or the record is deleted concurrently between the pre-check and the read-back.

Common situations: Rename flows that hit an existing name; two admins editing statuses at once; seeding scripts that update by stale _id after the workspace was re-seeded.

Related errors


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

Appendix: source

Thrown at apps/meteor/server/api/v1/custom-user-status.ts:269

		const userStatusData = {
			_id: this.bodyParams._id,
			name: this.bodyParams.name,
			statusType: this.bodyParams.statusType || '',
		};

		const customUserStatusToUpdate = await CustomUserStatus.findOneById(userStatusData._id);

		// Ensure the message exists
		if (!customUserStatusToUpdate) {
			return API.v1.failure(`No custom user status found with the id of "${userStatusData._id}".`);
		}

		await insertOrUpdateUserStatus(this.userId, userStatusData);

		const customUserStatus = await CustomUserStatus.findOneById(userStatusData._id);

		if (!customUserStatus) {
			throw new Meteor.Error('error-updating-custom-user-status', 'Error updating custom user status');
		}

		return API.v1.success({
			customUserStatus,
		});
	},
);

export type CustomUserStatusEndpoints = ExtractRoutesFromAPI<typeof customUserStatusEndpoints>;

declare module '@rocket.chat/rest-typings' {
	// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
	interface Endpoints extends CustomUserStatusEndpoints {}
}

View on GitHub (pinned to b2c16d5842)