RocketChat/Rocket.Chat · error · Meteor.Error

error-cursor-not-found

error-cursor-not-found

Error message

Cursor not found

What it means

mountCursorFromMessage derives the next/previous cursor from a boundary message of the fetched page: _updatedAt for type UPDATED, _deletedAt for DELETED (trash collection). If the boundary message lacks the required timestamp, the server cannot continue pagination and throws Meteor.Error 'error-cursor-not-found'. This is a server-side data-integrity failure, not a client-input error.

Source

Thrown at apps/meteor/server/publications/messages.ts:84

	}

	if (previous) {
		return { query: { $lt: extractTimestampFromCursor(previous) }, options: { ...options, sort: { _updatedAt: -1 } } };
	}

	return { query: { $gt: new Date(0) }, options };
}

export function mountCursorFromMessage(message: IMessage & { _deletedAt?: Date }, type: 'UPDATED' | 'DELETED'): string {
	if (type === 'UPDATED' && message._updatedAt) {
		return `${message._updatedAt.getTime()}`;
	}

	if (type === 'DELETED' && message._deletedAt) {
		return `${message._deletedAt.getTime()}`;
	}

	throw new Meteor.Error('error-cursor-not-found', 'Cursor not found', { method: 'messages/get' });
}

export function mountNextCursor(
	messages: IMessage[],
	count: number,
	type: CursorPaginationType,
	next?: string,
	previous?: string,
): string | null {
	if (messages.length === 0) {
		return null;
	}

	if (previous) {
		return mountCursorFromMessage(messages[0], type);
	}

	if (messages.length <= count && next) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Identify the offending documents (messages lacking _updatedAt, trash docs lacking _deletedAt) and backfill the missing timestamps
  2. Page past the broken boundary by re-fetching without a cursor (lastUpdate mode)
  3. Report the corrupted range upstream — these fields are set on every normal write, so their absence indicates abnormal data
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await getMessageHistory(rid, fromId, { type, next });
} catch (error) {
  if (error instanceof Meteor.Error && error.error === 'error-cursor-not-found') {
    // boundary message is missing its timestamp; fall back to lastUpdate-based sync
    return await getMessageHistory(rid, fromId, { lastUpdate: new Date(Date.now() - 60_000) });
  }
  throw error;
}

Prevention

When it happens

Trigger: A message document in the result page without _updatedAt, or a trashed document without _deletedAt — legacy documents predating the field, manual database edits, or a partial write that skipped the audit timestamp.

Common situations: Old installations after upgrades; imported data missing audit timestamps; direct Mongo modifications that dropped fields.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/b7ec41932da22efc. Report an issue: GitHub.