{"record":{"id":"9af5e5e35f6cd982","repo":"phacility/phabricator","slug":"rrule-freq-s-is-invalid-valid-frequencies-are","errorCode":null,"errorMessage":"RRULE FREQ \"%s\" is invalid. Valid frequencies are: %s.","messagePattern":"RRULE FREQ \"(.+?)\" is invalid\\. Valid frequencies are: (.+?)\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php","lineNumber":388,"sourceCode":"  }\n\n  public function getUntil() {\n    return $this->until;\n  }\n\n  public function setFrequency($frequency) {\n    static $map = array(\n      self::FREQUENCY_SECONDLY => self::SCALE_SECONDLY,\n      self::FREQUENCY_MINUTELY => self::SCALE_MINUTELY,\n      self::FREQUENCY_HOURLY => self::SCALE_HOURLY,\n      self::FREQUENCY_DAILY => self::SCALE_DAILY,\n      self::FREQUENCY_WEEKLY => self::SCALE_WEEKLY,\n      self::FREQUENCY_MONTHLY => self::SCALE_MONTHLY,\n      self::FREQUENCY_YEARLY => self::SCALE_YEARLY,\n    );\n\n    if (empty($map[$frequency])) {\n      throw new Exception(\n        pht(\n          'RRULE FREQ \"%s\" is invalid. Valid frequencies are: %s.',\n          $frequency,\n          implode(', ', array_keys($map))));\n    }\n\n    $this->frequency = $frequency;\n    $this->frequencyScale = $map[$frequency];\n\n    return $this;\n  }\n\n  public function getFrequency() {\n    return $this->frequency;\n  }\n\n  public function getFrequencyScale() {\n    return $this->frequencyScale;","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php#L370-L406","documentation":"Phabricator's RRULE implementation limits FREQ to the RFC 5545 frequencies SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY. setFrequency() throws for anything else, including nonstandard tokens like FORTNIGHTLY, lowercase 'daily', or a missing/null FREQ.","triggerScenarios":"setFrequency('BIWEEKLY'); a dict built from ICS with 'FREQ' => null (missing FREQ part); tokens not uppercased before use.","commonSituations":"Calendar producers emitting nonstandard frequencies; user-facing text like 'every two weeks' translated literally; case normalization skipped after storage.","solutions":["Express nonstandard intervals with a legal FREQ plus INTERVAL (BIWEEKLY -> WEEKLY with INTERVAL=2; FORTNIGHTLY likewise).","Uppercase the token: strtoupper($freq) before setting.","Reject RRULEs missing FREQ early in your import pipeline."],"exampleFix":"// before\n$rule->setFrequency('biweekly');\n// after\n$rule->setFrequency(PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY);\n$rule->setInterval(2);","handlingStrategy":"type-guard","validationCode":"$frequencies = array('SECONDLY','MINUTELY','HOURLY','DAILY',\n  'WEEKLY','MONTHLY','YEARLY');\n$freq = strtoupper(trim(idx($dict, 'FREQ', '')));\nif (!in_array($freq, $frequencies, true)) {\n  // map common nonstandard tokens or reject the rule\n  if ($freq === 'BIWEEKLY' || $freq === 'FORTNIGHTLY') {\n    $dict['FREQ'] = 'WEEKLY';\n    $dict['INTERVAL'] = 2;\n  } else {\n    // reject: no FREQ we can honor\n  }\n}","typeGuard":"function isValidRruleFrequency($freq) {\n  return in_array(strtoupper(trim((string)$freq)),\n    array('SECONDLY','MINUTELY','HOURLY','DAILY','WEEKLY','MONTHLY','YEARLY'), true);\n}","tryCatchPattern":null,"preventionTips":["Uppercase FREQ tokens before setting them.","Express nonstandard frequencies as a legal FREQ plus INTERVAL.","Reject RRULEs without a FREQ part at ingest."],"tags":["phutil","calendar","rrule","frequency","invalid-enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}