RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-date
error-invalid-date
Error message
Invalid date
What it means
getChannelHistory validates that oldest, when provided, is a real Date instance using {}.toString.call(oldest) !== '[object Date]', and throws 'error-invalid-date' otherwise. DDP method params must carry actual Date objects (EJSON preserves them across the wire); an ISO string like '2024-01-01T00:00:00.000Z' or an epoch number fails this check even though it looks date-like.
Source
Thrown at apps/meteor/server/meteor-methods/messages/getChannelHistory.ts:74
const room = await Rooms.findOneById(rid);
if (!room) {
return false;
}
// Make sure they can access the room
if (!(await Authorization.canReadRoom(room, { _id: fromUserId }))) {
return false;
}
// Ensure latest is always defined.
if (latest === undefined) {
latest = new Date();
}
// Verify oldest is a date if it exists
if (oldest !== undefined && {}.toString.call(oldest) !== '[object Date]') {
throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' });
}
const hiddenSystemMessages = settings.get<MessageTypesValues[]>('Hide_System_Messages');
const hiddenMessageTypes = getHiddenSystemMessages(room, hiddenSystemMessages);
const options: Record<string, unknown> = {
sort: {
ts: -1,
},
skip: offset,
limit: count,
};
const records =
oldest === undefined
? await Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(
rid,View on GitHub (pinned to b2c16d5842)
Solutions
- Pass Date objects: Meteor.call('getChannelHistory', { rid, oldest: new Date('2024-01-01T00:00:00.000Z') })
- If your API accepts strings, convert before invoking: oldest = new Date(oldest)
- Or use GET /v1/channels.history, whose date params are ISO strings parsed server-side (also the deprecation target)
Example fix
// before
Meteor.call('getChannelHistory', { rid, oldest: '2024-01-01T00:00:00.000Z' });
// after
Meteor.call('getChannelHistory', { rid, oldest: new Date('2024-01-01T00:00:00.000Z') }); Defensive patterns
Strategy: type-guard
Validate before calling
const oldestDate = typeof oldest === 'string' ? new Date(oldest) : oldest;
if (Number.isNaN(oldestDate?.getTime?.())) {
throw new TypeError('oldest must be a parseable date');
}
Meteor.call('getChannelHistory', { rid, oldest: oldestDate }); Type guard
function isDate(value: unknown): value is Date {
return {}.toString.call(value) === '[object Date]';
}
// usage: if (!isDate(oldest)) oldest = new Date(oldest); Prevention
- Never pass raw strings/numbers as date params to DDP methods — EJSON only preserves real Date objects
- Serialize method params with EJSON, not JSON.stringify, when round-tripping them
- Centralize date coercion at the boundary where user/URL input enters
When it happens
Trigger: Meteor.call('getChannelHistory', { rid, oldest: '2024-01-01T00:00:00.000Z' }) — passing an ISO string or a timestamp number; params serialized with plain JSON.stringify instead of EJSON; raw form/URL inputs fed to the method.
Common situations: Porting code from the REST API (channels.history accepts ISO date strings) to the DDP method; wrappers that round-trip params through plain JSON; date pickers returning strings.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/537140b18f4d83d4.
Report an issue: GitHub.