phacility/phabricator · error · Exception

Value "%s" in RRULE "%s" parameter is invalid: it must not b

Error message

Value "%s" in RRULE "%s" parameter is invalid: it must not be zero.

What it means

Some RRULE parameters disallow zero: BYMONTHDAY=0 and BYYEARDAY=0 are illegal under RFC5545 (there is no 'day zero'; negatives count from the end). assertByRange() is called with allow_zero=false for those parameters and throws on a zero value even though zero is in the numeric range.

Source

Thrown at src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php:1607

            'Value "%s" in RRULE "%s" parameter is invalid: values must be '.
            'integers.',
            $value,
            $source));
      }

      if ($value < $min || $value > $max) {
        throw new Exception(
          pht(
            'Value "%s" in RRULE "%s" parameter is invalid: it must be '.
            'between %s and %s.',
            $value,
            $source,
            $min,
            $max));
      }

      if (!$value && !$allow_zero) {
        throw new Exception(
          pht(
            'Value "%s" in RRULE "%s" parameter is invalid: it must not '.
            'be zero.',
            $value,
            $source));
      }
    }
  }

  private function getSetPositionState() {
    $scale = $this->getFrequencyScale();

    $parts = array();
    $parts[] = $this->stateYear;

    if ($scale == self::SCALE_WEEKLY) {
      $parts[] = $this->stateWeek;
    } else {

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Remove the zero value from the list
  2. If 'last day' was intended, use -1 instead of 0
  3. Sanitize BYMONTHDAY/BYYEARDAY inputs with array_filter($v, function($x) { return $x !== 0; }) before setting

Example fix

// before
$rrule = 'FREQ=MONTHLY;BYMONTHDAY=0';

// after
$rrule = 'FREQ=MONTHLY;BYMONTHDAY=-1';
Defensive patterns

Strategy: validation

Validate before calling

foreach (array('BYMONTHDAY', 'BYYEARDAY') as $key) {
  if (isset($parts[$key])) {
    foreach (explode(',', $parts[$key]) as $value) {
      if ((int)$value === 0) {
        throw new Exception($key.' must not contain zero.');
      }
    }
  }
}

Try / catch

try {
  $rule = PhutilCalendarRecurrenceRule::newFromRRule($rrule);
} catch (Exception $ex) {
  if (strpos($ex->getMessage(), 'must not be zero') !== false) {
    // Strip zero entries and retry.
  }
}

Prevention

When it happens

Trigger: An RRULE containing 'BYMONTHDAY=0' or 'BYYEARDAY=0', or programmatic setByMonthDay(array(0)) / setByYearDay(array(0)) on a rule that is then validated.

Common situations: Calendar UIs offering '0' as a selectable day; date math that subtracts into zero (e.g. computing day offsets with bc math or negative modulo bugs); imports from tools that normalize missing days to zero.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/3794160dc8a6e848. Report an issue: GitHub.