{"record":{"id":"62da2bb4d6827116","repo":"RocketChat/Rocket.Chat","slug":"error-cursor-conflict","errorCode":"error-cursor-conflict","errorMessage":"You cannot provide both \"next\" and \"previous\" parameters","messagePattern":"You cannot provide both \"next\" and \"previous\" parameters","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/publications/messages.ts","lineNumber":253,"sourceCode":"\t  }\n\t| false\n\t| IMessage[]\n\t| { messages: IMessage[]; firstUnread?: any; unreadNotLoaded?: number }\n> => {\n\tif (!(await canAccessRoomIdAsync(rid, fromId))) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'messages/get' });\n\t}\n\n\tif (type && !['UPDATED', 'DELETED'].includes(type)) {\n\t\tthrow new Meteor.Error('error-type-param-not-supported', 'The \"type\" parameter must be either \"UPDATED\" or \"DELETED\"');\n\t}\n\n\tif ((next || previous) && !type) {\n\t\tthrow new Meteor.Error('error-type-param-required', 'The \"type\" parameter is required when using the \"next\" or \"previous\" parameters');\n\t}\n\n\tif (next && previous) {\n\t\tthrow new Meteor.Error('error-cursor-conflict', 'You cannot provide both \"next\" and \"previous\" parameters');\n\t}\n\n\tif ((next || previous) && lastUpdate) {\n\t\tthrow new Meteor.Error(\n\t\t\t'error-cursor-and-lastUpdate-conflict',\n\t\t\t'The attributes \"next\", \"previous\" and \"lastUpdate\" cannot be used together',\n\t\t);\n\t}\n\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) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/publications/messages.ts#L235-L271","documentation":"Cursor pagination in messages/get is one-directional per request: supplying both next and previous throws Meteor.Error 'error-cursor-conflict' before any data is fetched. Each response cursor pair indicates where to continue in each direction, but only one may be used per call.","triggerScenarios":"Calling messages/get with both next and previous set — most often a client echoing the whole response.cursor { next, previous } object verbatim into the next request.","commonSituations":"Mirroring the cursor object from a previous response; merging paging params from two branches of UI state (infinite scroll up + down); request builders that spread all stored params unconditionally.","solutions":["Send only the direction you are paging: next to go forward, previous to go backward","Keep a single active cursor in state, not both","Treat a null cursor as 'no more pages in that direction' and omit it from the next request"],"exampleFix":"// before\nMeteor.call('messages/get', rid, { type, next: cursor.next ?? undefined, previous: cursor.previous ?? undefined }); // both set -> error-cursor-conflict\n\n// after\nconst paging = direction === 'older' ? { next: cursor.next ?? undefined } : { previous: cursor.previous ?? undefined };\nMeteor.call('messages/get', rid, { type, ...paging });","handlingStrategy":"validation","validationCode":"const hasSingleCursorDirection = (params: { next?: string; previous?: string }): boolean =>\n  !(params.next && params.previous);","typeGuard":"const isSingleDirectionPaging = (p: unknown): p is { next?: string; previous?: string } => {\n  const v = p as { next?: string; previous?: string };\n  return !(v.next && v.previous);\n};","tryCatchPattern":null,"preventionTips":["Send exactly one cursor per request — the direction you are paging in","Do not spread a stored cursor object into the request; pick one field explicitly","Treat null cursors from responses as end-of-pages and omit them from subsequent requests"],"tags":["pagination","messages-api","parameter-validation","cursor"],"backgroundTag":"conflicting-query-parameters","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}