{"record":{"id":"57d3f78d9b092b6a","repo":"RocketChat/Rocket.Chat","slug":"error-status-not-allowed","errorCode":"error-status-not-allowed","errorMessage":"Invisible status is disabled","messagePattern":"Invisible status is disabled","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/users.ts","lineNumber":2075,"sourceCode":"\t\t\tconst statusExpiresAt = expiresAt ? new Date(expiresAt) : undefined;\n\t\t\tif (statusExpiresAt && Number.isNaN(statusExpiresAt.getTime())) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-date', 'Invalid expiresAt date string', {\n\t\t\t\t\tmethod: 'users.setStatus',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (statusExpiresAt && statusExpiresAt.getTime() <= Date.now()) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-date', 'expiresAt must be a future date', {\n\t\t\t\t\tmethod: 'users.setStatus',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// If status is missing (message-only update), keep the user's chosen status (statusDefault),\n\t\t\t// not the computed status — otherwise a transient auto-away/offline gets pinned as a manual claim.\n\t\t\tconst effectiveStatus = status || user.statusDefault || ('online' as UserStatus);\n\n\t\t\tif (effectiveStatus === 'offline' && !settings.get('Accounts_AllowInvisibleStatusOption')) {\n\t\t\t\tthrow new Meteor.Error('error-status-not-allowed', 'Invisible status is disabled', {\n\t\t\t\t\tmethod: 'users.setStatus',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait Presence.setStatus(user._id, effectiveStatus, message, statusExpiresAt);\n\n\t\t\treturn API.v1.success();\n\t\t},\n\t)\n\t.get(\n\t\t'users.getStatus',\n\t\t{\n\t\t\tauthRequired: true,\n\t\t\tquery: isUsersGetStatusParamsGET,\n\t\t\tresponse: {\n\t\t\t\t200: ajv.compile<{ _id: string; status: string; connectionStatus?: string; statusSource?: string; statusExpiresAt?: string }>({\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {","sourceCodeStart":2057,"sourceCodeEnd":2093,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/users.ts#L2057-L2093","documentation":"Thrown by POST /api/v1/users.setStatus when the effective status resolves to 'offline' while Accounts_AllowInvisibleStatusOption is false. Effective status is the requested status, falling back to user.statusDefault then 'online', so even a message-only update can trip this if the user's default status is offline. Code: error-status-not-allowed, method 'users.setStatus'.","triggerScenarios":"POST users.setStatus {\"status\":\"offline\"} with the setting disabled; message-only update for a user whose statusDefault is 'offline'; clients that mirror a chat-app 'invisible' mode onto Rocket.Chat status.","commonSituations":"Workspace policy requiring real presence; setting flipped after users already set offline defaults; federation/bridge tools syncing invisible state from another platform.","solutions":["Don't send status offline when the setting is off; omit status to keep current/default","If invisible presence is required, have the admin enable Accounts_AllowInvisibleStatusOption","Reset affected users' statusDefault away from offline before message-only updates","Read the setting up front in multi-workspace clients"],"exampleFix":"// before\nawait sdk.post('users.setStatus', { status: 'offline', message: 'do not disturb' });\n// after\nawait sdk.post('users.setStatus', { status: 'busy', message: 'do not disturb' });","handlingStrategy":"validation","validationCode":"const allowInvisible = await getSetting('Accounts_AllowInvisibleStatusOption');\nconst effective = body.status ?? user.statusDefault ?? 'online';\nif (effective === 'offline' && !allowInvisible) throw new Error('invisible status disabled');\nawait sdk.post('users.setStatus', body);","typeGuard":"const isStatusAllowed = (status: string, allowInvisible: boolean): status is 'online'|'busy'|'away'|'offline' => ['online','busy','away','offline'].includes(status) && (status !== 'offline' || allowInvisible);","tryCatchPattern":"try { await sdk.post('users.setStatus', body); } catch (e) { if (e.response?.data?.errorType === 'error-status-not-allowed') { body.status = 'busy'; await sdk.post('users.setStatus', body); } else throw e; }","preventionTips":["Hide the offline option in clients when the setting is off","Remember statusDefault can also resolve to offline","Don't mirror other platforms' invisible mode blindly"],"tags":["rest-api","presence","status","settings"],"backgroundTag":"feature-disabled-by-setting","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}