phacility/phabricator · error · Exception
RRULE specifies BYMONTHDAY with FREQ set to WEEKLY, which vi
Error message
RRULE specifies BYMONTHDAY with FREQ set to WEEKLY, which violates RFC5545.
What it means
RFC5545 states that BYMONTHDAY MUST NOT be combined with FREQ=WEEKLY, because 'day of month' has no meaning inside a weekly cycle. PhutilCalendarRecurrenceRule::resetSource() enforces this as soon as the rule starts evaluating, so any weekly rule carrying BYMONTHDAY fails fast instead of producing wrong dates.
Source
Thrown at src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php:574
self::getWeekdayIndex($week_start);
$this->weekStart = $week_start;
return $this;
}
public function getWeekStart() {
return $this->weekStart;
}
public function resetSource() {
$frequency = $this->getFrequency();
if ($this->getByMonthDay()) {
switch ($frequency) {
case self::FREQUENCY_WEEKLY:
// RFC5545: "The BYMONTHDAY rule part MUST NOT be specified when the
// FREQ rule part is set to WEEKLY."
throw new Exception(
pht(
'RRULE specifies BYMONTHDAY with FREQ set to WEEKLY, which '.
'violates RFC5545.'));
break;
default:
break;
}
}
if ($this->getByYearDay()) {
switch ($frequency) {
case self::FREQUENCY_DAILY:
case self::FREQUENCY_WEEKLY:
case self::FREQUENCY_MONTHLY:
// RFC5545: "The BYYEARDAY rule part MUST NOT be specified when the
// FREQ rule part is set to DAILY, WEEKLY, or MONTHLY."
throw new Exception(View on GitHub (pinned to 5720a38cfe)
Solutions
- Remove the BYMONTHDAY part if a plain weekly recurrence is intended
- Switch FREQ to MONTHLY or DAILY if the day-of-month filter is actually required
- Pre-validate imported RRULEs: reject BYMONTHDAY whenever FREQ=WEEKLY before handing the rule to the parser
Example fix
// before $rrule = 'FREQ=WEEKLY;BYMONTHDAY=15;BYDAY=MO'; // after $rrule = 'FREQ=WEEKLY;BYDAY=MO';
Defensive patterns
Strategy: validation
Validate before calling
$parts = array();
foreach (explode(';', $rrule) as $part) {
$kv = explode('=', $part, 2);
$parts[$kv[0]] = idx($kv, 1);
}
if (idx($parts, 'FREQ') === 'WEEKLY' && isset($parts['BYMONTHDAY'])) {
throw new Exception('BYMONTHDAY is not allowed with FREQ=WEEKLY (RFC5545).');
} Try / catch
try {
$rule->getEvents();
} catch (Exception $ex) {
if (strpos($ex->getMessage(), 'BYMONTHDAY') !== false) {
// Strip BYMONTHDAY and retry with a sanitized rule.
}
throw $ex;
} Prevention
- Treat RFC5545 MUST NOT combinations as import-time rejections, not runtime surprises
- When generating rules from templates, derive allowed parts from FREQ instead of reusing a fixed part list
- Unit-test each generated rule shape against the parser before storing it
When it happens
Trigger: An RRULE like 'FREQ=WEEKLY;BYMONTHDAY=15', or building the rule in code via setFrequency(self::FREQUENCY_WEEKLY) followed by setByMonthDay(array(15)) and then calling getEvents()/resetSource().
Common situations: Machine-generated or hand-written .ics files that reuse BYMONTHDAY across frequencies; code that copies a monthly rule template and only changes FREQ to WEEKLY; calendar imports from buggy producers.
Related errors
- RRULE BYDAY value "%s" has an offset with magnitude "%s", bu
- RRULE specifies BYYEARDAY with FREQ of DAILY, WEEKLY or MONT
- Value "%s" in RRULE "%s" parameter is invalid: it must be be
- Value "%s" in RRULE "%s" parameter is invalid: it must not b
- RRULE specifies BYSETPOS with FREQ "%s", but this is invalid
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/b2cc1c44ddeb2be8.
Report an issue: GitHub.