{"record":{"id":"dccf3d6b03f37419","repo":"phacility/phabricator","slug":"rrule-specifies-byyearday-with-freq-of-daily-week","errorCode":null,"errorMessage":"RRULE specifies BYYEARDAY with FREQ of DAILY, WEEKLY or MONTHLY, which violates RFC5545.","messagePattern":"RRULE specifies BYYEARDAY with FREQ of DAILY, WEEKLY or MONTHLY, which violates RFC5545\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php","lineNumber":592,"sourceCode":"          throw new Exception(\n            pht(\n              'RRULE specifies BYMONTHDAY with FREQ set to WEEKLY, which '.\n              'violates RFC5545.'));\n          break;\n        default:\n          break;\n      }\n\n    }\n\n    if ($this->getByYearDay()) {\n      switch ($frequency) {\n        case self::FREQUENCY_DAILY:\n        case self::FREQUENCY_WEEKLY:\n        case self::FREQUENCY_MONTHLY:\n          // RFC5545: \"The BYYEARDAY rule part MUST NOT be specified when the\n          // FREQ rule part is set to DAILY, WEEKLY, or MONTHLY.\"\n          throw new Exception(\n            pht(\n              'RRULE specifies BYYEARDAY with FREQ of DAILY, WEEKLY or '.\n              'MONTHLY, which violates RFC5545.'));\n        default:\n          break;\n      }\n    }\n\n    // TODO\n    // RFC5545: \"The BYDAY rule part MUST NOT be specified with a numeric\n    // value when the FREQ rule part is not set to MONTHLY or YEARLY.\"\n    // RFC5545: \"Furthermore, the BYDAY rule part MUST NOT be specified with a\n    // numeric value with the FREQ rule part set to YEARLY when the BYWEEKNO\n    // rule part is specified.\"\n\n\n    $date = $this->getStartDateTime();\n","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php#L574-L610","documentation":"RFC5545 forbids BYYEARDAY when FREQ is DAILY, WEEKLY, or MONTHLY, since a year-day index cannot be applied on those cycles. PhutilCalendarRecurrenceRule::resetSource() throws during rule initialization whenever both a BYYEARDAY list and one of those frequencies are present.","triggerScenarios":"An RRULE such as 'FREQ=MONTHLY;BYYEARDAY=100', 'FREQ=DAILY;BYYEARDAY=1,366', or code calling setByYearDay(...) on a rule whose frequency is DAILY/WEEKLY/MONTHLY, followed by evaluation.","commonSituations":"Copy-pasted RRULE templates where FREQ was changed but BYYEARDAY kept; .ics producers that emit BYYEARDAY unconditionally; imports of rules authored against non-RFC tools.","solutions":["Change FREQ to YEARLY (the only frequency where BYYEARDAY is meaningful)","Remove the BYYEARDAY part and express the intent with BYMONTH/BYMONTHDAY instead","Pre-screen imported RRULEs for the forbidden BYYEARDAY + DAILY/WEEKLY/MONTHLY combinations"],"exampleFix":"// before\n$rrule = 'FREQ=MONTHLY;BYYEARDAY=100';\n\n// after\n$rrule = 'FREQ=YEARLY;BYYEARDAY=100';","handlingStrategy":"validation","validationCode":"$forbidden = array('DAILY', 'WEEKLY', 'MONTHLY');\nif (isset($parts['BYYEARDAY']) && in_array(idx($parts, 'FREQ'), $forbidden, true)) {\n  throw new Exception('BYYEARDAY is not allowed with FREQ=DAILY/WEEKLY/MONTHLY.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  $rule = PhutilCalendarRecurrenceRule::newFromRRule($rrule);\n  $rule->getEvents();\n} catch (Exception $ex) {\n  // Map to an import validation error for the offending .ics line.\n}","preventionTips":["Maintain a compatibility table of FREQ x BY* parts and check rules against it on import","Reject or drop unsupported combinations with a logged warning rather than storing failing rules","Cover forbidden combinations in fixture-based .ics import tests"],"tags":["rrule","icalendar","rfc5545","calendar","byyearday"],"backgroundTag":"rrule-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}