RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-dates

error-invalid-dates

Error message

From date cannot be after To date

What it means

Thrown by POST rooms.mail (type 'file') when the user-supplied dateFrom is later than dateTo (after dateTo is bumped by one day internally). The server builds a date window for the export and rejects inverted ranges.

Source

Thrown at apps/meteor/server/api/v1/rooms.ts:1035

			throw new Meteor.Error('error-invalid-room');
		}

		const user = await Users.findOneById(this.userId);

		if (!user || !(await canAccessRoomAsync(room, user))) {
			throw new Meteor.Error('error-not-allowed', 'Not Allowed');
		}

		if (type === 'file') {
			const { dateFrom, dateTo } = this.bodyParams;
			const { format } = this.bodyParams;

			const convertedDateFrom = dateFrom ? new Date(dateFrom) : new Date(0);
			const convertedDateTo = dateTo ? new Date(dateTo) : new Date();
			convertedDateTo.setDate(convertedDateTo.getDate() + 1);

			if (convertedDateFrom > convertedDateTo) {
				throw new Meteor.Error('error-invalid-dates', 'From date cannot be after To date');
			}

			void dataExport.sendFile(
				{
					rid,
					format,
					dateFrom: convertedDateFrom,
					dateTo: convertedDateTo,
				},
				user,
			);
			return API.v1.success();
		}

		if (type === 'email') {
			const { toUsers, toEmails, subject, messages } = this.bodyParams;

			if ((!toUsers || toUsers.length === 0) && (!toEmails || toEmails.length === 0)) {

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Enforce dateFrom <= dateTo in the picker and disable the submit button otherwise.
  2. Swap or normalize the two values if inverted before sending.
  3. Send both as ISO-8601 UTC to avoid timezone-driven inversions.

Example fix

// before
await rest.post('/api/v1/rooms.mail', { rid, type:'file', dateFrom, dateTo });

// after
if (new Date(dateFrom) > new Date(dateTo)) [dateFrom, dateTo] = [dateTo, dateFrom];
await rest.post('/api/v1/rooms.mail', {
  rid, type:'file',
  dateFrom: new Date(dateFrom).toISOString(),
  dateTo: new Date(dateTo).toISOString(),
});
Defensive patterns

Strategy: validation

Validate before calling

const from = new Date(dateFrom).getTime();
const to = new Date(dateTo).getTime();
if (isNaN(from) || isNaN(to)) throw new Error('invalid dates');
if (from > to) [dateFrom, dateTo] = [dateTo, dateFrom];

Type guard

function isValidDateRange(a: unknown, b: unknown): boolean {
  const f = Date.parse(String(a)); const t = Date.parse(String(b));
  return !isNaN(f) && !isNaN(t) && f <= t;
}

Try / catch

try {
  await rest.post(url, { rid, type:'file', dateFrom, dateTo });
} catch (e) {
  if (isMeteorError(e, 'error-invalid-dates')) {
    // swap and retry
  } else throw e;
}

Prevention

When it happens

Trigger: POST /api/v1/rooms.mail with { type:'file', dateFrom, dateTo } where new Date(dateFrom) > new Date(dateTo). Note dateTo gets +1 day before the comparison, so only ranges off by more than a day trip it.

Common situations: UI date pickers letting the user pick a 'from' after 'to'; timezone confusion making the same calendar day compare as inverted; swapped form fields; default values that don't make sense.

Related errors


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