{"record":{"id":"766267498db208fb","repo":"RocketChat/Rocket.Chat","slug":"error-roomid-param-invalid","errorCode":"error-roomId-param-invalid","errorMessage":"The \"${paramName}\" query parameter must be a valid date.","messagePattern":"The \"(.+?)\" query parameter must be a valid date\\.","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/emoji-custom.ts","lineNumber":59,"sourceCode":"});\n\nconst emojiCustomDeleteResponseSchema = ajv.compile<void>({\n\ttype: 'object',\n\tproperties: {\n\t\tsuccess: { type: 'boolean', enum: [true] },\n\t},\n\trequired: ['success'],\n\tadditionalProperties: false,\n});\n\nfunction validateDateParam(paramName: string, paramValue: string | undefined): Date | undefined {\n\tif (!paramValue) {\n\t\treturn undefined;\n\t}\n\n\tconst date = new Date(paramValue);\n\tif (isNaN(date.getTime())) {\n\t\tthrow new Meteor.Error('error-roomId-param-invalid', `The \"${paramName}\" query parameter must be a valid date.`);\n\t}\n\n\treturn date;\n}\n\nconst emojiCustomListResponseSchema = ajv.compile<{\n\temojis: { update: IEmojiCustom[]; remove: WithId<RocketChatRecordDeleted<IEmojiCustom>>[] };\n}>({\n\ttype: 'object',\n\tproperties: {\n\t\temojis: {\n\t\t\ttype: 'object',\n\t\t\tproperties: {\n\t\t\t\tupdate: { type: 'array', items: { type: 'object' } },\n\t\t\t\tremove: { type: 'array', items: { type: 'object' } },\n\t\t\t},\n\t\t\trequired: ['update', 'remove'],\n\t\t},","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/emoji-custom.ts#L41-L77","documentation":"Thrown by the validateDateParam helper (used by emoji-custom list/sync endpoints) when a provided date parameter cannot construct a valid Date. NOTABLE BUG: the error CODE is 'error-roomId-param-invalid' (copy-paste from elsewhere) while the MESSAGE correctly reports the date param is invalid. Clients branching on the code will be misled; match on HTTP 400 or the message text instead.","triggerScenarios":"Passing ?since=foo, an empty string in a date field, a locale-formatted date, or a non-ISO value to an emoji-custom endpoint that calls validateDateParam.","commonSituations":"Client serializes a Date without toISOString; user-typed date in a regional format; empty string sent for an optional date param instead of omitting it.","solutions":["Send an ISO-8601 UTC timestamp for any date param, or omit the param entirely when not needed.","Do not branch on error code 'error-roomId-param-invalid' here — it is misnamed; match HTTP 400 or the message.","Pre-validate with new Date(value); if isNaN, drop the param."],"exampleFix":"// before\nconst url = `/api/v1/emoji-custom.list?since=${userInput}`; // userInput may be '12/04/24'\n// after\nconst since = userInput ? new Date(userInput).toISOString() : undefined;\nconst qs = since ? `?since=${encodeURIComponent(since)}` : '';\nconst url = `/api/v1/emoji-custom.list${qs}`;","handlingStrategy":"validation","validationCode":"function safeDateParam(value) {\n  if (!value) return undefined;\n  const d = new Date(value);\n  if (isNaN(d.getTime())) throw new Error('invalid date param');\n  return d.toISOString();\n}\nconst since = safeDateParam(userInput); // append to query only if defined","typeGuard":"function isParsableDate(s): s is string { return typeof s === 'string' && !isNaN(new Date(s).getTime()); }","tryCatchPattern":"try { await listEmojiCustom({ since }); }\ncatch (e) {\n  // NOTE: code is misnamed 'error-roomId-param-invalid'; match HTTP 400 or message\n  if (e?.error === 'error-roomId-param-invalid' || /valid date/i.test(e.reason || '')) { /* drop date param, retry */) }\n  else throw e;\n}","preventionTips":["Always send ISO-8601 UTC for date params, or omit them.","Do not branch on error code for this endpoint — it is misnamed.","Validate with new Date() and isNaN before constructing the URL."],"tags":["emoji-custom","validation","date","bug","rest-api"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}