{"record":{"id":"5ca93d50f504d3d2","repo":"RocketChat/Rocket.Chat","slug":"the-property-end-query-parameter-must-be-a-va","errorCode":null,"errorMessage":"The \"${property}.end\" query parameter must be a valid date.","messagePattern":"The \"(.+?)\\.end\" query parameter must be a valid date\\.","errorType":"validation","errorClass":"Error","httpStatus":400,"severity":"warning","filePath":"apps/meteor/server/api/v1/omnichannel/rooms.ts","lineNumber":19,"sourceCode":"import { LivechatRooms } from '@rocket.chat/models';\nimport { isGETLivechatRoomsParams } from '@rocket.chat/rest-typings';\n\nimport { API } from '../..';\nimport { findRooms } from './lib/rooms';\nimport { hasPermissionAsync } from '../../../lib/authorization/hasPermission';\nimport { getPaginationItems } from '../../lib/getPaginationItems';\n\nconst validateDateParams = (property: string, date?: string) => {\n\tlet parsedDate: { start?: string; end?: string } | undefined = undefined;\n\tif (date) {\n\t\tparsedDate = JSON.parse(date) as { start?: string; end?: string };\n\t}\n\n\tif (parsedDate?.start && isNaN(Date.parse(parsedDate.start))) {\n\t\tthrow new Error(`The \"${property}.start\" query parameter must be a valid date.`);\n\t}\n\tif (parsedDate?.end && isNaN(Date.parse(parsedDate.end))) {\n\t\tthrow new Error(`The \"${property}.end\" query parameter must be a valid date.`);\n\t}\n\treturn parsedDate;\n};\n\nconst isBoolean = (value?: string | boolean): boolean => value === 'true' || value === 'false' || typeof value === 'boolean';\n\nAPI.v1.addRoute(\n\t'livechat/rooms',\n\t{ authRequired: true, validateParams: isGETLivechatRoomsParams },\n\t{\n\t\tasync get() {\n\t\t\tconst { offset, count } = await getPaginationItems(this.queryParams);\n\t\t\tconst { sort, fields, query } = await this.parseJsonQuery();\n\t\t\tconst { agents, departmentId, open, tags, roomName, onhold, queued, units } = this.queryParams;\n\t\t\tconst { createdAt, customFields, closedAt } = this.queryParams;\n\n\t\t\tconst createdAtParam = validateDateParams('createdAt', createdAt);\n\t\t\tconst closedAtParam = validateDateParams('closedAt', closedAt);","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/rooms.ts#L1-L37","documentation":"Thrown by validateDateParams in GET livechat/rooms when the createdAt/closedAt JSON param has an `.end` field that Date.parse cannot interpret. Symmetric with the .start check; only the field name in the message differs. Any non-empty end value failing Date.parse triggers it.","triggerScenarios":"GET livechat/rooms?closedAt={\"start\":\"2021-01-01\",\"end\":\"tomorrow\"} — the end value 'tomorrow' (or any non-ISO string) is rejected. Same risk for relative words, locale dates, or malformed numbers.","commonSituations":"Range filter where the user picked a start date but typed/omitted end date in free text; client sends end as a Unix epoch number-as-string the parser rejects; mismatched date formats between start and end.","solutions":["Always send end as ISO 8601, matching the start format.","If end is optional, omit it from the JSON object instead of sending null or empty string.","Client-side guard: `if (end && isNaN(Date.parse(end))) warnUser();`.","URL-encode the serialized JSON query param."],"exampleFix":"// before\nGET('/api/v1/livechat/rooms?createdAt=' + JSON.stringify({ start: '2021-01-01', end: userInputEnd }));\n\n// after\nconst endIso = userInputEnd ? new Date(userInputEnd).toISOString() : undefined;\nconst range = endIso ? { start: startIso, end: endIso } : { start: startIso };\nGET('/api/v1/livechat/rooms?createdAt=' + encodeURIComponent(JSON.stringify(range)));","handlingStrategy":"validation","validationCode":"function buildDateParam(start?: string, end?: string) {\n  const out: { start?: string; end?: string } = {};\n  if (start) { if (isNaN(Date.parse(start))) throw new ClientError('bad start'); out.start = new Date(start).toISOString(); }\n  if (end) { if (isNaN(Date.parse(end))) throw new ClientError('bad end'); out.end = new Date(end).toISOString(); }\n  return Object.keys(out).length ? JSON.stringify(out) : undefined;\n}","typeGuard":"const isIsoDate = (s: unknown): s is string => typeof s === 'string' && !isNaN(Date.parse(s));","tryCatchPattern":"try {\n  await GET('/api/v1/livechat/rooms', { closedAt: buildDateParam(start, end) });\n} catch (e) {\n  if (/must be a valid date/i.test(e.message)) { showDateError(); return; }\n  throw e;\n}","preventionTips":["Use ISO 8601 for both start and end consistently.","Omit end when unneeded instead of sending null/empty.","URL-encode the JSON param."],"tags":["omnichannel","livechat","query-params","date-validation","rooms-list"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}