{"record":{"id":"f257799e947d181d","repo":"RocketChat/Rocket.Chat","slug":"error-param-required-f25779","errorCode":"error-param-required","errorMessage":"The \"type\" or \"lastUpdate\" parameters must be provided","messagePattern":"The \"type\" or \"lastUpdate\" parameters must be provided","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/publications/messages.ts","lineNumber":280,"sourceCode":"\n\t// `fromTs` only bounds the query on the `lastUpdate` path; neither cursor pagination nor the channel\n\t// history fallback honors it, so accepting it there would silently widen the result set.\n\tif (fromTs && !lastUpdate) {\n\t\tthrow new Meteor.Error('error-fromTs-requires-lastUpdate', 'The \"fromTs\" parameter can only be used together with \"lastUpdate\"');\n\t}\n\n\tconst hasCursorPagination = !!((next || previous) && count !== null && type);\n\n\tif (!hasCursorPagination && !lastUpdate) {\n\t\treturn getChannelHistory({ rid, fromUserId: fromId, latest: latestDate, oldest: oldestDate, inclusive, count, unreads });\n\t}\n\n\tif (lastUpdate) {\n\t\treturn handleWithoutPagination(rid, lastUpdate, fromTs);\n\t}\n\n\tif (!type) {\n\t\tthrow new Meteor.Error('error-param-required', 'The \"type\" or \"lastUpdate\" parameters must be provided');\n\t}\n\n\treturn handleCursorPagination(type, rid, count, next, previous);\n};\n\nMeteor.methods<ServerMethods>({\n\tasync 'messages/get'(\n\t\trid,\n\t\t{ lastUpdate, latestDate = new Date(), oldestDate, inclusive = false, count = 20, unreads = false, next, previous, type },\n\t) {\n\t\tcheck(rid, String);\n\n\t\tconst fromId = Meteor.userId();\n\n\t\tif (!fromId) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'messages/get' });\n\t\t}\n","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/publications/messages.ts#L262-L298","documentation":"Defensive assertion in getMessageHistory: after the plain channel-history fallback and the lastUpdate path, the function requires 'type' to proceed with cursor pagination. In the shipped control flow every parameter combination that lacks lastUpdate is captured by the earlier fallback (line 271), so this throw fires only when a caller bypasses or refactors that fallback — e.g. a direct caller of getMessageHistory with a changed branch order. Note the related trap: passing count: null with a cursor makes hasCursorPagination false and silently falls back to plain history.","triggerScenarios":"Direct server-side calls to getMessageHistory with a parameter set that no longer matches any mode after local refactors; payloads where count is explicitly null so hasCursorPagination stays false while lastUpdate is absent and the fallback was skipped.","commonSituations":"Custom branches of Rocket.Chat that reorder the mode checks; code that copies getMessageHistory into another service without the line-271 fallback.","solutions":["Provide 'type' (\"UPDATED\" or \"DELETED\") together with next/previous and a non-null count","Provide 'lastUpdate' to select the sync mode","Keep the plain-history fallback in place if you refactor this function"],"exampleFix":"// before\nawait getMessageHistory(rid, uid, { next, count: null });\n\n// after\nawait getMessageHistory(rid, uid, { next, type: 'UPDATED', count: 50 });","handlingStrategy":"validation","validationCode":"const mode = params.lastUpdate ? 'sync' : (params.next || params.previous) && params.type && params.count != null ? 'cursor' : 'history';\nif (mode === 'cursor' && !params.type) throw new Error('type is required for cursor pagination');\nif (mode === 'cursor') delete params.count === null && delete params.count;","typeGuard":"type PaginationMode = { mode: 'history' } | { mode: 'sync'; lastUpdate: Date } | { mode: 'cursor'; type: 'UPDATED' | 'DELETED'; cursor?: string; count: number };","tryCatchPattern":"try { await getMessageHistory(rid, uid, params); } catch (e) { if (e.error === 'error-param-required') { /* supply type or lastUpdate per desired mode */ } }","preventionTips":["Never pass count: null when using cursors — it silently disables cursor pagination","Keep the plain-history fallback branch intact when refactoring getMessageHistory"],"tags":["meteor","messages-get","pagination","defensive-check","rocket-chat"],"backgroundTag":"missing-required-parameter","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T08:17:14.275Z"}