Repository navigation
Booking page crashes with "RangeError: Invalid time value" on invalid ?month= or ?date= query params #30302
Copy link
Copy link
Open
Labels
🐛 bugSomething isn't workingSomething isn't working
Description
Issue Summary
The Booker reads ?month= and ?date= from the URL without validating them. A malformed value makes the whole booking page crash with the generic "It's not you, it's us" error page. Other odd values are accepted silently and lead to confusing states: months in the past, months that roll over (2026-13 shows January 2027), and absurd years (99999-01 shows September 9999).
These params appear in shareable/booking links and are easy to get wrong (hand-edited links, truncated URLs, broken integrations that build links), so a bad link currently dead-ends the booker instead of falling back to a sensible default.
Steps to Reproduce
- Open any public booking page with an invalid param, e.g.
http://localhost:3000/pro/30min?layout=month_view&month=garbage. - Or
.../pro/30min?layout=month_view&date=garbage.
Results observed on a local dev instance (seeded pro user, event 30min, today = 2026-10-06):
| Query params | Result |
|---|---|
month=garbage |
Page replaced by error screen: RangeError: Invalid time value |
date=garbage |
Same crash (even with a valid month=2026-10) |
month=2026-13 |
Header shows "January 2027"; URL keeps month=2026-13 (dayjs overflow, not normalized) |
month=2026-1 |
Header shows "January 2026", a past month, with a "No availability" dialog |
month=2020-01 |
"January 2020" with a "No availability" dialog (unreachable through the UI) |
date=2026-02-31 |
Rolls over to "March 2026", a past month |
month=99999-01 |
Renders "September 9999" |
month=2076-10 |
Renders October 2076 with bookable days (the event has an unlimited period, so this may be intended) |
month= (empty) |
Falls back to the current month (fine) |
Actual Results
- Invalid values crash the page. Console:
RangeError: Invalid time value at Date.toISOStringinuseTimesForSchedule(packages/features/schedules/hooks/useTimesForSchedule.ts, themonthDayjs.startOf("month").toISOString()calls around lines 117-124). - Past, overflowing and extreme values are accepted as-is into the Booker store; the URL is not rewritten.
Expected Results
- An invalid or unparseable
month/datenever crashes the page; the Booker falls back to the current month (and rewrites the URL to match). - Past months/dates fall back to the current month, since they can't be reached through the UI.
- Values like
2026-13or2026-02-31are treated as invalid, not silently rolled over.
Technical details
- The values enter through the Booker store initial state:
packages/features/bookings/Booker/store.ts(month:initializer readinggetQueryParam("month"), around lines 520-525, andselectedDate: getQueryParam("date"), around line 457). Neither is validated. - Suggested fix: validate with strict dayjs parsing (
YYYY-MM/YYYY-MM-DDwithstrict = true) and clamp to>= current monthin one small helper used by both initializers, with unit tests (Vitest,TZ=UTC). No UI or translation changes needed. - Open question for maintainers: for event types with an unlimited booking period, should there be an upper bound on how far ahead
?month=may point (e.g. 12 or 24 months)? Every month triggers a full slots computation, so an arbitrary far-future month is a cheap way to make the server do work. I'd rather ask than assume, and I would not add a bound in the first PR unless asked. - I considered a "polite modal" for out-of-range dates, but a silent fallback needs no new UI or strings and keeps the change small. Happy to do the modal instead if maintainers prefer.
- I searched existing issues and PRs and found nothing about validating these params. Closest: merged fix: booker atom not resetting month query param #14715, fix: Ensure previous slots do appear if the month search param is removed #18097, feat: prevent automatic query parameters when opening booking page #18132, and closed fix: Ensure correct fallback to current month when 'month' query param is … #18096, which touched
monthparam handling but not validation. - I'm happy to open a PR for this.
- Environment: Cal.diy
mainat54343aa, local dev server (Next 16), Chrome, macOS. Not verified on a production build.
Evidence

Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
🐛 bugSomething isn't workingSomething isn't working
Activity
WojciechCzechowski commentedon Oct 7, 2026
Hi @nishantsingh02, thanks for picking this up. I saw your fork PR (nishantsingh02#1) and the validation helper looks like a good approach.
One thing to flag: that PR was merged into your fork's
main, so the change isn't incalcom/cal.diyyet. For it to land here, a PR needs to be opened from your branch againstcalcom/cal.diymain.A small note on the change itself: it sanitizes the store's initial
month/datevalues, but as far as I can tell the invalid value stays in the address bar (e.g.?month=garbageisn't rewritten to the current month). That doesn't crash anymore, but the URL and the displayed month can disagree, and a shared link keeps the bad value. It may be worth rewriting the param to the sanitized value, or deciding explicitly that leaving it is fine.Are you planning to open the upstream PR? If so, go ahead. If you'd rather not, I can open it myself, with tests. Let me know either way so we don't duplicate work. If I haven't heard back in a couple of days, I'll go ahead and open one.