phacility/phabricator · error · Exception

Sequence "%s" is not valid for event!

Error message

Sequence "%s" is not valid for event!

What it means

When a child instance of a recurring event is materialized without an explicit start datetime, the parent computes the start from the instance's stored sequence index via newSequenceIndexDateTime(). That method returns null when the index no longer maps to an occurrence — the recurrence set is empty, or a COUNT limit cuts off before this sequence — and materialization throws.

Source

Thrown at src/applications/calendar/storage/PhabricatorCalendarEvent.php:219

    $this
      ->setHostPHID($parent->getHostPHID())
      ->setIsAllDay($parent->getIsAllDay())
      ->setIcon($parent->getIcon())
      ->setSpacePHID($parent->getSpacePHID())
      ->setViewPolicy($parent->getViewPolicy())
      ->setEditPolicy($parent->getEditPolicy())
      ->setName($parent->getName())
      ->setDescription($parent->getDescription())
      ->setIsCancelled($parent->getIsCancelled());

    if ($start) {
      $start_datetime = $start;
    } else {
      $sequence = $this->getSequenceIndex();
      $start_datetime = $parent->newSequenceIndexDateTime($sequence);

      if (!$start_datetime) {
        throw new Exception(
          pht(
            'Sequence "%s" is not valid for event!',
            $sequence));
      }
    }

    $duration = $parent->newDuration();
    $end_datetime = $start_datetime->newRelativeDateTime($duration);

    $this
      ->setStartDateTime($start_datetime)
      ->setEndDateTime($end_datetime);

    if ($parent->isImportedEvent()) {
      $full_uid = $parent->getImportUID().'/'.$start_datetime->getEpoch();

      // NOTE: We don't attach the import source because this gets called
      // from CalendarEventQuery while building ghosts, before we've loaded

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Repair the data: delete the stale child instance rows (they will be regenerated as ghosts on demand) or fix the sequence index to match the parent's current recurrence
  2. Verify the parent's recurrence is intact (frequency, count, until) before querying with ghost generation
  3. If the parent was intentionally shortened, run the repair/reindex so orphaned sequences are pruned

Example fix

// before (instance row for sequence 8 while parent rule is COUNT=5)
$event->newStub($viewer, $sequence)->save();

// after: validate against the parent before touching the instance
$parent = $event->getInstanceOfEvent();
if (!$parent || !$parent->isValidSequenceIndex($viewer, $sequence)) {
  continue; // stale instance; skip or prune it
}
Defensive patterns

Strategy: try-catch

Validate before calling

$parent = id(new PhabricatorCalendarEventQuery())
  ->setViewer($viewer)
  ->withPHIDs(array($event->getInstanceOfEventPHID()))
  ->executeOne();
if ($parent && !$parent->isValidSequenceIndex($viewer, $sequence)) {
  // Skip or prune the stale instance instead of materializing it.
  continue;
}

Try / catch

try {
  $datetime = $parent->newSequenceIndexDateTime($sequence);
} catch (Exception $ex) {
  // Sequence no longer resolves under the parent's current rule:
  // drop the stale child row and let ghosts regenerate as needed.
  $event->delete();
  continue;
}

Prevention

When it happens

Trigger: A stored instance row (e.g. one with a cancelled/edited sequence) whose sequence index exceeds the parent's current COUNT (the rule was edited to 'repeat 5 times' while an instance for sequence 8 exists), or whose parent lost its recurrence data so newRecurrenceSet() returns empty.

Common situations: Editing a recurring event's occurrence count or DTSTART after instances were created; data restored from backup where parent and child rows are out of sync; corrupted imports that wrote child rows with bogus sequence indexes.

Related errors


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