{"record":{"id":"f2e4208e018a6fc0","repo":"RocketChat/Rocket.Chat","slug":"error-updatedsince-param-invalid","errorCode":"error-updatedSince-param-invalid","errorMessage":"The \"updatedSince\" query parameter must be a valid date.","messagePattern":"The \"updatedSince\" query parameter must be a valid date\\.","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/chat.ts","lineNumber":1162,"sourceCode":"\t\t\t\t\t},\n\t\t\t\t\trequired: ['threads', 'success'],\n\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t}),\n\t\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t\t},\n\t\t},\n\t\tasync function action() {\n\t\t\tconst { rid } = this.queryParams;\n\t\t\tconst { query, fields, sort } = await this.parseJsonQuery();\n\t\t\tconst { updatedSince } = this.queryParams;\n\t\t\tlet updatedSinceDate;\n\t\t\tif (!settings.get<boolean>('Threads_enabled')) {\n\t\t\t\tthrow new Meteor.Error('error-not-allowed', 'Threads Disabled');\n\t\t\t}\n\n\t\t\tif (isNaN(Date.parse(updatedSince))) {\n\t\t\t\tthrow new Meteor.Error('error-updatedSince-param-invalid', 'The \"updatedSince\" query parameter must be a valid date.');\n\t\t\t} else {\n\t\t\t\tupdatedSinceDate = new Date(updatedSince);\n\t\t\t}\n\t\t\tconst user = await Users.findOneById(this.userId, { projection: { _id: 1 } });\n\t\t\tconst room = await Rooms.findOneById(rid, { projection: { ...roomAccessAttributes, t: 1, _id: 1 } });\n\n\t\t\tif (!room || !user || !(await canAccessRoomAsync(room, user))) {\n\t\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not Allowed');\n\t\t\t}\n\t\t\tconst threadQuery = Object.assign({}, query, { rid, tcount: { $exists: true } });\n\t\t\treturn API.v1.success({\n\t\t\t\tthreads: {\n\t\t\t\t\tupdate: await Messages.find(\n\t\t\t\t\t\t{ ...threadQuery, _updatedAt: { $gt: updatedSinceDate } },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsort,\n\t\t\t\t\t\t\tprojection: fields,\n\t\t\t\t\t\t},","sourceCodeStart":1144,"sourceCodeEnd":1180,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/chat.ts#L1144-L1180","documentation":"Thrown by GET chat.syncThreadsList when the updatedSince query parameter cannot be parsed as a date: the endpoint runs isNaN(Date.parse(updatedSince)) and throws Meteor.Error('error-updatedSince-param-invalid'). Because updatedSince is destructured from queryParams, omitting it yields undefined, Date.parse(undefined) is NaN, so the call fails both for missing and malformed values — updatedSince is effectively required on sync endpoints.","triggerScenarios":"Calling chat.syncThreadsList without updatedSince, with an empty value, or with a non-ISO string such as '01-02-2024' variants the JS parser rejects, e.g. 'yesterday', '2024/13/45', or a raw Unix timestamp like '1700000000'.","commonSituations":"Porting code from the non-sync chat.getThreadsList (where updatedSince does not exist) and forgetting the param; passing epoch seconds instead of an ISO string; passing a date formatted by a locale-specific formatter.","solutions":["Pass an ISO 8601 UTC string: updatedSince=2024-06-01T00:00:00.000Z.","If you meant 'everything', first call chat.getThreadsList once, store the max _updatedAt, then use that timestamp for subsequent syncs.","Encode the date client-side with new Date().toISOString() to avoid locale formatting issues."],"exampleFix":"// before\nfetch('/api/v1/chat.syncThreadsList?rid=RID&updatedSince=' + Date.now());\n\n// after\nfetch('/api/v1/chat.syncThreadsList?rid=RID&updatedSince=' + new Date(lastSync).toISOString());","handlingStrategy":"validation","validationCode":"const since = params.updatedSince;\nif (since === undefined || Number.isNaN(Date.parse(since))) {\n  throw new Error('updatedSince must be an ISO 8601 date string');\n}\n// Rocket.Chat expects ISO 8601; reject epoch numbers and locale formats\nif (typeof since === 'number') throw new Error('pass new Date(ms).toISOString(), not epoch');","typeGuard":"function isIsoDateString(v: unknown): v is string {\n  return typeof v === 'string' && !Number.isNaN(Date.parse(v)) && /Z$|[+-]\\d{2}:?\\d{2}$/.test(v.trim());\n}","tryCatchPattern":"try { await api.get('chat.syncThreadsList', { rid, updatedSince }); }\ncatch (e) {\n  if (e.error === 'error-updatedSince-param-invalid') { since = new Date().toISOString(); retry(); } else throw e;\n}","preventionTips":["Always serialize dates with toISOString().","Remember sync endpoints require updatedSince — the plain get variants do not accept it."],"tags":["rocketchat","rest-api","threads","query-param","date-parsing"],"backgroundTag":"invalid-query-parameter","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"}