phacility/phabricator · error · Exception

RRULE COUNT value "%s" is invalid: count must be at least 1.

Error message

RRULE COUNT value "%s" is invalid: count must be at least 1.

What it means

PhutilCalendarRecurrenceRule::setCount() rejects counts below 1. RFC 5545 defines COUNT as a positive occurrence count; COUNT=0 would mean a rule with no occurrences and is invalid. Note that the string '0' passes the earlier digit-regex normalization, casts to int 0, and then fails here.

Source

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

          $weekday,
          implode(', ', $constants)));
    }

    return $map[$weekday];
  }

  public function setStartDateTime(PhutilCalendarDateTime $start) {
    $this->startDateTime = $start;
    return $this;
  }

  public function getStartDateTime() {
    return $this->startDateTime;
  }

  public function setCount($count) {
    if ($count < 1) {
      throw new Exception(
        pht(
          'RRULE COUNT value "%s" is invalid: count must be at least 1.',
          $count));
    }

    $this->count = $count;
    return $this;
  }

  public function getCount() {
    return $this->count;
  }

  public function setUntil(PhutilCalendarDateTime $until) {
    $this->until = $until;
    return $this;
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Remove the COUNT part entirely (rule then runs to UNTIL or forever) or set it to at least 1.
  2. Validate external input: if ((int)$count < 1) drop the COUNT component rather than passing it through.
  3. Only clamp with max(1, $count) if a single occurrence is an acceptable business default; otherwise reject the RRULE.

Example fix

// before
$rule->setCount(0);
// after
// omit setCount() entirely, or:
$rule->setCount(1);
Defensive patterns

Strategy: validation

Validate before calling

$count = idx($dict, 'COUNT');
if ($count !== null) {
  $count = (int)$count;
  if ($count < 1) {
    unset($dict['COUNT']); // no meaningful COUNT; let the rule run to UNTIL/forever
  } else {
    $dict['COUNT'] = $count;
  }
}

Type guard

function isValidRruleCount($count) {
  return is_int($count) && $count >= 1;
}

Prevention

When it happens

Trigger: An ICS RRULE containing COUNT=0; newFromDictionary(array('FREQ' => 'DAILY', 'COUNT' => 0)); programmatic rules built from user input allowing zero.

Common situations: Broken calendar exports; edge-case values from other vendors; forms that default a repeat count field to 0.

Related errors


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