RocketChat/Rocket.Chat · error · Meteor.Error
error-creating-custom-user-status
error-creating-custom-user-status
Error message
Error creating custom user status
What it means
Thrown by POST custom-user-status.create as a post-condition check: after insertOrUpdateUserStatus runs, the endpoint re-reads CustomUserStatus.findOneByName(name) and throws Meteor.Error('error-creating-custom-user-status') if the status cannot be found. In practice insertOrUpdateUserStatus can return without creating/updating (for example when a status with the same name in a different case already exists), so the read-back misses and this fires.
Solutions
- List existing statuses first (GET /api/v1/custom-user-status.list) and skip creation when the name already exists case-insensitively.
- Normalize the name before sending (trim; decide one casing policy).
- If creation genuinely should have worked, check server logs for insert errors and retry with a distinct name.
Example fix
// before
await api.post('custom-user-status.create', { name, statusType });
// after — de-duplicate against existing statuses (case-insensitive)
const { statuses } = await api.get('custom-user-status.list');
if (!statuses.some(s => s.name.toLowerCase() === name.trim().toLowerCase())) {
await api.post('custom-user-status.create', { name: name.trim(), statusType });
} Defensive patterns
Strategy: validation
Validate before calling
async function createStatusIfAbsent(api, name: string, statusType: string) {
const { statuses } = await api.get('custom-user-status.list');
const exists = statuses.some(s => s.name.toLowerCase() === name.trim().toLowerCase());
if (!exists) await api.post('custom-user-status.create', { name: name.trim(), statusType });
} Try / catch
try { await api.post('custom-user-status.create', { name, statusType }); }
catch (e) {
if (e.error === 'error-creating-custom-user-status') { await refreshStatuses(); /* likely duplicate-name guard */ } else throw e;
} Prevention
- Trim and case-normalize names before creating.
- Make seeding idempotent: list first, create only missing entries.
When it happens
Trigger: POSTing { "name": "Busy", "statusType": "busy" } when a status named 'busy'/'BUSY' already exists (case-insensitive duplicate blocked inside insertOrUpdateUserStatus); name that normalizes to an existing entry; or the insert failing validation.
Common situations: Admin tooling that seeds statuses on every deploy and hits the duplicate-name guard; names differing only by case or surrounding whitespace; retries after a partially completed first request.
Related errors
- error-updating-custom-user-status
- error-e2e-key-reset-in-progress
- error-invalid-param
- error-not-allowed
- error-updatedSince-param-invalid
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/5b8139c117ba1d50.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/custom-user-status.ts:171
body: isCustomUserStatusCreateProps,
response: {
200: customUserStatusCreateResponseSchema,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
403: validateForbiddenErrorResponse,
},
},
async function action() {
const userStatusData = {
name: this.bodyParams.name,
statusType: this.bodyParams.statusType || '',
};
await insertOrUpdateUserStatus(this.userId, userStatusData);
const customUserStatus = await CustomUserStatus.findOneByName(userStatusData.name);
if (!customUserStatus) {
throw new Meteor.Error('error-creating-custom-user-status', 'Error creating custom user status');
}
return API.v1.success({
customUserStatus,
});
},
);
const isCustomUserStatusDeleteProps = ajv.compile<{ customUserStatusId: string }>({
type: 'object',
properties: {
customUserStatusId: { type: 'string', minLength: 1 },
},
required: ['customUserStatusId'],
additionalProperties: false,
});
const customUserStatusDeleteResponseSchema = ajv.compile<void>({View on GitHub (pinned to b2c16d5842)