{"record":{"id":"9c3b1fb2d5e85510","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-date","errorCode":"error-invalid-date","errorMessage":"Invalid expiresAt date string","messagePattern":"Invalid expiresAt date string","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/users.ts","lineNumber":2023,"sourceCode":"\t\t\t\t\treturn getUserFromParams(this.bodyParams);\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\tif (!user) {\n\t\t\t\treturn API.v1.forbidden();\n\t\t\t}\n\n\t\t\tconst { status, message, expiresAt } = this.bodyParams;\n\n\t\t\tif (message && !settings.get('Accounts_AllowUserStatusMessageChange')) {\n\t\t\t\tthrow new Meteor.Error('error-not-allowed', 'Change status is not allowed', {\n\t\t\t\t\tmethod: 'users.setStatus',\n\t\t\t\t});\n\t\t\t}\n\n\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});","sourceCodeStart":2005,"sourceCodeEnd":2041,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/users.ts#L2005-L2041","documentation":"Thrown by POST users.setStatus when the 'expiresAt' body field is present but cannot be parsed by the Date constructor into a valid timestamp (new Date(expiresAt).getTime() is NaN). This is the malformed-date case, distinct from the past-date case (609).","triggerScenarios":"POST /api/v1/users.setStatus with expiresAt set to a non-ISO string like 'tomorrow', '2024-13-45', an empty string after trimming, or a locale-formatted date the constructor cannot parse.","commonSituations":"Client formats the date with a locale-specific string instead of ISO 8601. Time-zone offset missing. Empty string slips through from an unfilled form field that is still included in the payload.","solutions":["Send expiresAt as an ISO 8601 string (e.g. new Date().toISOString()) or a millisecond timestamp.","Validate the date client-side before submission: ensure !Number.isNaN(new Date(value).getTime()).","Omit expiresAt entirely when no expiry is intended rather than sending an empty or placeholder string."],"exampleFix":"// before\nPOST('/api/v1/users.setStatus', { status:'away', expiresAt: 'tomorrow at 5' })\n\n// after\nconst d = new Date('tomorrow at 5')\nif (Number.isNaN(d.getTime())) throw new ClientError('bad date')\nPOST('/api/v1/users.setStatus', { status:'away', expiresAt: d.toISOString() })","handlingStrategy":"validation","validationCode":"function validExpiresAt(v) {\n  if (v == null) return true;\n  const d = new Date(v);\n  return !Number.isNaN(d.getTime());\n}\nif (!validExpiresAt(body.expiresAt)) delete body.expiresAt;","typeGuard":"function isParsableDate(v) {\n  if (v == null) return true;\n  const d = new Date(v);\n  return d instanceof Date && !Number.isNaN(d.getTime());\n}","tryCatchPattern":"try { await POST('/api/v1/users.setStatus', body); }\ncatch (e) {\n  if (e?.error === 'error-invalid-date') { delete body.expiresAt; await POST('/api/v1/users.setStatus', body); return; }\n  throw e;\n}","preventionTips":["Always send expiresAt as ISO 8601 via toISOString().","Validate with new Date(v).getTime() before submitting.","Omit expiresAt entirely when no expiry is intended."],"tags":["api","users","presence","status","date","validation"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}