calcom/cal.diy · error · BadRequestException
Start date must be before end date.
Error message
Start date must be before end date.
What it means
Thrown by isStartBeforeEnd() when both start and end are present but start.getTime() > end.getTime(). The OOO window must be non-negative in duration; an inverted range is rejected. Equality (start === end) is permitted because the comparison is strictly greater-than.
Source
Thrown at apps/api/v2/src/modules/ooo/services/ooo.service.ts:51
) {}
formatOooReason(ooo: OutOfOfficeEntry) {
return {
...ooo,
reason: ooo.reasonId
? OOO_REASON_ID_TO_REASON[ooo.reasonId as keyof typeof OOO_REASON_ID_TO_REASON]
: OOO_REASON_ID_TO_REASON[1],
};
}
isStartBeforeEnd(start?: Date, end?: Date) {
if ((end && !start) || (start && !end)) {
throw new BadRequestException("Please specify both ooo start and end time.");
}
if (start && end) {
if (start.getTime() > end.getTime()) {
throw new BadRequestException("Start date must be before end date.");
}
}
return true;
}
async checkUserEligibleForRedirect(userId: number, toUserId?: number) {
if (toUserId) {
const user = await this.usersRepository.findUserOOORedirectEligible(userId, toUserId);
if (!user) {
throw new BadRequestException("Cannot redirect to this user.");
}
}
}
async checkExistingOooRedirect(userId: number, start?: Date, end?: Date, toUserId?: number) {
if (start && end) {
const existingOooRedirect = await this.oooRepository.findExistingOooRedirect(
userId,View on GitHub (pinned to 176037d0af)
Solutions
- Client-side: assert start <= end before submitting, and swap the values if the user picked them in reverse.
- Compute end from start plus a positive delta (e.g. start + N days) rather than constructing both independently.
- Render a disabled submit button until start <= end in the UI to fail fast.
Example fix
// before
const end = new Date(start.getTime() - days * 86400000); // inverted
// after
const end = new Date(start.getTime() + days * 86400000);
// guard before submit
if (start.getTime() > end.getTime()) throw new Error('start must precede end'); Defensive patterns
Strategy: validation
Validate before calling
function assertOrder(start: Date, end: Date) {
if (start.getTime() > end.getTime())
throw new Error('start must be <= end');
return { start: start.toISOString(), end: end.toISOString() };
} Type guard
const isValidRange = (start?: Date, end?: Date): boolean => !start || !end ? true : start.getTime() <= end.getTime();
Prevention
- Compute end as start + positive delta rather than constructing independently.
- Disable submit when start > end in the picker.
- Watch for month/day transposition and DST shifts that can invert a window.
When it happens
Trigger: POST/PATCH /v2/ooo where the client orders the bounds backwards, computes end by subtracting instead of adding a duration, or swaps day/month in one of the dates so the parsed instant inverts.
Common situations: Date pickers returning end before start when the user clears and re-picks; timezone math that shifts start past end across a DST boundary; copy-paste fixtures with reversed dates; month/day transposition (MM-DD vs DD-MM) on one field.
Related errors
- Invalid Date.
- Please specify both ooo start and end time.
- Cannot redirect to this user.
- Booking redirect infinite not allowed.
- Cannot redirect to self.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/de738b0128f97f92.
Report an issue: GitHub.