RocketChat/Rocket.Chat · error · Meteor.Error

error-roomId-param-invalid

error-roomId-param-invalid

Error message

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

What it means

BUG-WARNING: the code and message disagree. The logic validates the 'updatedSince' (a.k.a. lastUpdate) DATE on GET subscriptions.get, but the thrown code is 'error-roomId-param-invalid' (about a room id) while the message talks about a date. Treat this as 'the updatedSince date could not be parsed'. A non-ISO/non-Date-parseable value triggers it.

Source

Thrown at apps/meteor/server/api/v1/subscriptions.ts:60

});

API.v1.get(
	'subscriptions.get',
	{
		authRequired: true,
		query: isSubscriptionsGetProps,
		response: {
			200: subscriptionsGetResponseSchema,
			401: validateUnauthorizedErrorResponse,
		},
	},
	async function action() {
		const { updatedSince } = this.queryParams;

		let updatedSinceDate: Date | undefined;
		if (updatedSince) {
			if (isNaN(Date.parse(updatedSince))) {
				throw new Meteor.Error('error-roomId-param-invalid', 'The "lastUpdate" query parameter must be a valid date.');
			}
			updatedSinceDate = new Date(updatedSince);
		}

		const result = await getSubscriptions(this.userId, updatedSinceDate);

		return API.v1.success(
			Array.isArray(result)
				? {
						update: result,
						remove: [],
					}
				: result,
		);
	},
);

const subscriptionsGetOneResponseSchema = ajv.compile<{ subscription: ISubscription | null }>({

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Send updatedSince as ISO-8601 via new Date().toISOString() and URL-encode it.
  2. Omit updatedSince to fetch all subscriptions.
  3. Client-side: if isNaN(Date.parse(value)) is true, do not send the param.
  4. File/track the code/message mismatch upstream — the code should be 'error-updatedSince-param-invalid'.

Example fix

// before
rest.get(`/api/v1/subscriptions.get?updatedSince=${Date.now()}`);

// after
const since = new Date().toISOString();
rest.get(`/api/v1/subscriptions.get?updatedSince=${encodeURIComponent(since)}`);
Defensive patterns

Strategy: validation

Validate before calling

let url = '/api/v1/subscriptions.get';
if (updatedSince) {
  if (isNaN(Date.parse(updatedSince))) throw new Error('updatedSince must be a valid date');
  url += `?updatedSince=${encodeURIComponent(updatedSince)}`;
}

Type guard

function isValidIsoDate(s: unknown): s is string {
  return typeof s === 'string' && !isNaN(Date.parse(s));
}

Try / catch

try {
  await rest.get(url);
} catch (e) {
  // NOTE: code is 'error-roomId-param-invalid' but the cause is a bad DATE
  if (isMeteorError(e, 'error-roomId-param-invalid')) {
    await rest.get('/api/v1/subscriptions.get'); // retry without cursor
  } else throw e;
}

Prevention

When it happens

Trigger: GET /api/v1/subscriptions.get?updatedSince=<unparseable> where Date.parse returns NaN. Despite the code name, no roomId is involved here.

Common situations: Passing a Unix epoch number; locale-formatted date string; URL encoding that mangles the timestamp; copying a value from a different API field format.

Related errors


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