RocketChat/Rocket.Chat · error · Meteor.Error

error-updatedSince-param-invalid

error-updatedSince-param-invalid

Error message

The "updatedSince" query parameter must be a valid date.

What it means

Thrown by GET chat.syncThreadsList when updatedSince is supplied but Date.parse(updatedSince) is NaN. Checked at chat.ts:1155. Note: the check fires only when updatedSince is truthy but unparseable; an empty updatedSince is treated as 'no delta' and does not throw here.

Source

Thrown at apps/meteor/server/api/v1/chat.ts:1156

					},
					required: ['threads', 'success'],
					additionalProperties: false,
				}),
				400: validateBadRequestErrorResponse,
				401: validateUnauthorizedErrorResponse,
			},
		},
		async function action() {
			const { rid } = this.queryParams;
			const { query, fields, sort } = await this.parseJsonQuery();
			const { updatedSince } = this.queryParams;
			let updatedSinceDate;
			if (!settings.get<boolean>('Threads_enabled')) {
				throw new Meteor.Error('error-not-allowed', 'Threads Disabled');
			}

			if (isNaN(Date.parse(updatedSince))) {
				throw new Meteor.Error('error-updatedSince-param-invalid', 'The "updatedSince" query parameter must be a valid date.');
			} else {
				updatedSinceDate = new Date(updatedSince);
			}
			const user = await Users.findOneById(this.userId, { projection: { _id: 1 } });
			const room = await Rooms.findOneById(rid, { projection: { ...roomAccessAttributes, t: 1, _id: 1 } });

			if (!room || !user || !(await canAccessRoomAsync(room, user))) {
				throw new Meteor.Error('error-not-allowed', 'Not Allowed');
			}
			const threadQuery = Object.assign({}, query, { rid, tcount: { $exists: true } });
			return API.v1.success({
				threads: {
					update: await Messages.find(
						{ ...threadQuery, _updatedAt: { $gt: updatedSinceDate } },
						{
							sort,
							projection: fields,
						},

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Send updatedSince as ISO-8601 UTC: 2024-06-01T00:00:00.000Z.
  2. Generate via new Date().toISOString() and URL-encode the result.
  3. If you want a full snapshot (no delta), omit updatedSince entirely rather than sending garbage.

Example fix

// before
GET /api/v1/chat.syncThreadsList?rid=GENERAL&updatedSince=1717200000
// after
GET /api/v1/chat.syncThreadsList?rid=GENERAL&updatedSince=2024-06-01T00:00:00.000Z
Defensive patterns

Strategy: validation

Validate before calling

function toIsoUpdatedSince(v: string | number | Date): string {
  const d = v instanceof Date ? v : new Date(v);
  if (isNaN(d.getTime())) {
    throw new Error('updatedSince must be a valid ISO date; got: ' + String(v));
  }
  return d.toISOString();
}

u.searchParams.set('updatedSince', toIsoUpdatedSince(lastThreadSync));

Type guard

const isValidIsoDate = (s: unknown): boolean =>
  typeof s === 'string' && !isNaN(Date.parse(s));

Try / catch

try {
  await GET(syncThreadsUrl);
} catch (e) {
  if ((e as any)?.error === 'error-updatedSince-param-invalid') {
    // reset cursor to a known-good ISO value and retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /api/v1/chat.syncThreadsList?rid=...&updatedSince=1717200000 (epoch number as string), updatedSince=06/01/2024, or any non-ISO format.

Common situations: Same date-format pitfalls as error 365: non-ISO formatter, missing 'Z' suffix, locale string, URL-encoding mangling.

Related errors


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