briannesbitt/Carbon · error · UnreachableException
Could not calculate period end after iterating 10000 times.
Error message
Could not calculate period end after iterating 10000 times.
What it means
When calculateEnd() cannot derive the end arithmetically (e.g. custom filters exist, so the recurrences alone don't give the last date), it falls back to iterateUntilEnd(), stepping through the whole period date by date for up to END_MAX_ATTEMPTS (10000) iterations. If the true end lies farther than 10000 steps away, the search aborts with UnreachableException instead of running forever (src/Carbon/CarbonPeriod.php:2007).
Source
Thrown at src/Carbon/CarbonPeriod.php:2007
if ($this->filters === [[static::RECURRENCES_FILTER, null]]) {
return $this->getStartDate()->avoidMutation()->add(
$this->getDateInterval()->times(
$this->carbonRecurrences - ($this->isStartExcluded() ? 0 : 1),
),
);
}
return null;
}
private function iterateUntilEnd(): ?CarbonInterface
{
$attempts = 0;
$date = null;
foreach ($this as $date) {
if (++$attempts > static::END_MAX_ATTEMPTS) {
throw new UnreachableException(
'Could not calculate period end after iterating '.static::END_MAX_ATTEMPTS.' times.',
);
}
}
return $date;
}
/**
* Returns true if the current period overlaps the given one (if 1 parameter passed)
* or the period between 2 dates (if 2 parameters passed).
*
* @param CarbonPeriod|\DateTimeInterface|Carbon|CarbonImmutable|string $rangeOrRangeStart
* @param \DateTimeInterface|Carbon|CarbonImmutable|string|null $rangeEnd
*
* @return bool
*/
public function overlaps(mixed $rangeOrRangeStart, mixed $rangeEnd = null): boolView on GitHub (pinned to b13f05955d)
Solutions
- Compute the end arithmetically yourself when there are no filters: $start->copy()->add($interval->times($n - 1))
- Calculate from an unfiltered copy with the same start/interval/recurrences (that path is O(1)), then keep the filters on the real period
- Coarsen the interval or bound recurrences so the step count stays under CarbonPeriod::END_MAX_ATTEMPTS (10000)
Example fix
// before
$end = CarbonPeriod::create('2000-01-01', 'P1D')
->setRecurrences(20000)
->calculateEnd(); // > 10000 iterations -> UnreachableException
// after — arithmetic, no iteration
$end = Carbon::parse('2000-01-01')->add(days: 20000 - 1); Defensive patterns
Strategy: fallback
Validate before calling
$steps = $period->getRecurrences() ?? INF;
if (is_finite($steps) && $steps > CarbonPeriod::END_MAX_ATTEMPTS && \count($period->getFilters()) > 1) {
// calculateEnd() would iterate each step; compute arithmetically instead
$end = $period->getStartDate()->copy()->add($period->getDateInterval()->times((int) $steps - 1));
} else {
$end = $period->calculateEnd();
} Try / catch
try {
$end = $period->calculateEnd();
} catch (\Carbon\Exceptions\UnreachableException $e) {
// too many steps: derive the end arithmetically from an unfiltered twin
$end = CarbonPeriod::create($period->getStartDate(), $period->getDateInterval())
->setRecurrences($period->getRecurrences())
->calculateEnd();
} Prevention
- Avoid calculateEnd() on filtered, high-recurrence periods; compute the bound arithmetically
- Keep intervals proportional to the range (don't step per-second over months)
- Know the caps: CarbonPeriod::END_MAX_ATTEMPTS = 10000
When it happens
Trigger: CarbonPeriod::create('2000-01-01', 'P1D')->setRecurrences(20000)->calculateEnd(); a period with custom filters spanning more than 10000 steps; a PT1S interval over several months; daily occurrences across 30+ years with a filter attached.
Common situations: Fine-grained intervals over long ranges; high recurrence counts in schedules; reports computing the 'last occurrence' of a filtered schedule.
Related errors
- Could not calculate period end without either explicit end o
- Argument 1 passed to {$class}::{$method}() must be an instan
- Invalid ISO 8601 specification: {$iso}.
- $anchorDay parameter must not be set for $mode OverflowMode:
- You must specify $end or $recurrences but not both
AI-assisted analysis of briannesbitt/Carbon@b13f05955d (2026-08-17).
Data as JSON: /api/errors/5ffae9e583709772.
Report an issue: GitHub.