{"record":{"id":"5b8139c117ba1d50","repo":"RocketChat/Rocket.Chat","slug":"error-creating-custom-user-status","errorCode":"error-creating-custom-user-status","errorMessage":"Error creating custom user status","messagePattern":"Error creating custom user status","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/custom-user-status.ts","lineNumber":171,"sourceCode":"\t\tbody: isCustomUserStatusCreateProps,\n\t\tresponse: {\n\t\t\t200: customUserStatusCreateResponseSchema,\n\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t\t403: validateForbiddenErrorResponse,\n\t\t},\n\t},\n\tasync function action() {\n\t\tconst userStatusData = {\n\t\t\tname: this.bodyParams.name,\n\t\t\tstatusType: this.bodyParams.statusType || '',\n\t\t};\n\n\t\tawait insertOrUpdateUserStatus(this.userId, userStatusData);\n\n\t\tconst customUserStatus = await CustomUserStatus.findOneByName(userStatusData.name);\n\t\tif (!customUserStatus) {\n\t\t\tthrow new Meteor.Error('error-creating-custom-user-status', 'Error creating custom user status');\n\t\t}\n\n\t\treturn API.v1.success({\n\t\t\tcustomUserStatus,\n\t\t});\n\t},\n);\n\nconst isCustomUserStatusDeleteProps = ajv.compile<{ customUserStatusId: string }>({\n\ttype: 'object',\n\tproperties: {\n\t\tcustomUserStatusId: { type: 'string', minLength: 1 },\n\t},\n\trequired: ['customUserStatusId'],\n\tadditionalProperties: false,\n});\n\nconst customUserStatusDeleteResponseSchema = ajv.compile<void>({","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/custom-user-status.ts#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait api.post('custom-user-status.create', { name, statusType });\n\n// after — de-duplicate against existing statuses (case-insensitive)\nconst { statuses } = await api.get('custom-user-status.list');\nif (!statuses.some(s => s.name.toLowerCase() === name.trim().toLowerCase())) {\n  await api.post('custom-user-status.create', { name: name.trim(), statusType });\n}","handlingStrategy":"validation","validationCode":"async function createStatusIfAbsent(api, name: string, statusType: string) {\n  const { statuses } = await api.get('custom-user-status.list');\n  const exists = statuses.some(s => s.name.toLowerCase() === name.trim().toLowerCase());\n  if (!exists) await api.post('custom-user-status.create', { name: name.trim(), statusType });\n}","typeGuard":null,"tryCatchPattern":"try { await api.post('custom-user-status.create', { name, statusType }); }\ncatch (e) {\n  if (e.error === 'error-creating-custom-user-status') { await refreshStatuses(); /* likely duplicate-name guard */ } else throw e;\n}","preventionTips":["Trim and case-normalize names before creating.","Make seeding idempotent: list first, create only missing entries."],"tags":["rocketchat","rest-api","custom-user-status","duplicate-entry","creation-failed"],"backgroundTag":"resource-creation-failed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}