briannesbitt/Carbon · error · InvalidArgumentException
$anchorDay parameter must not be set for $mode OverflowMode:
Error message
$anchorDay parameter must not be set for $mode OverflowMode::{$mode->name} What it means
CarbonPeriod::monthly()/quarterly()/yearly() accept an $anchorDay (day of month to pin, e.g. 'the 31st') together with an OverflowMode controlling what happens when a month has fewer days. An anchor day only has meaning with the default OverflowMode::AnchorDay; the NoOverflow and Overflow modes define their own day handling, so passing a non-null $anchorDay alongside them is contradictory and rejected in getStartAndEndForCyclePeriod() (src/Carbon/CarbonPeriod.php:576).
Source
Thrown at src/Carbon/CarbonPeriod.php:576
*/
protected static function addMissingParts(string $source, string $target): string
{
$pattern = '/'.preg_replace('/\d+/', '[0-9]+', preg_quote($target, '/')).'$/';
$result = preg_replace($pattern, $target, $source, 1, $count);
return $count ? $result : $target;
}
private static function getStartAndEndForCyclePeriod(
DateTimeInterface|string|int|null $start = null,
DateTimeInterface|string|int|null $end = null,
?int $recurrences = null,
?int $anchorDay = null,
OverflowMode $mode = OverflowMode::AnchorDay,
): array {
if ($anchorDay !== null && $mode !== OverflowMode::AnchorDay) {
throw new InvalidArgumentException(
'$anchorDay parameter must not be set for $mode OverflowMode::'.$mode->name,
);
}
if ($end !== null && $recurrences !== null) {
throw new InvalidArgumentException(
'You must specify $end or $recurrences but not both',
);
}
if (\is_int($start)) {
$start = CarbonImmutable::createFromTimestamp($start);
} elseif (\is_string($start)) {
$start = CarbonImmutable::parse($start);
}
$start ??= CarbonImmutable::now();
View on GitHub (pinned to b13f05955d)
Solutions
- Drop the anchor day (pass null) when using NoOverflow or Overflow modes
- Keep the anchor day and stay on the default mode (omit $mode, i.e. OverflowMode::AnchorDay)
- Use named arguments to remove positional mix-ups: CarbonPeriod::monthly(start: $start, end: $end, mode: OverflowMode::NoOverflow)
Example fix
// before
$period = CarbonPeriod::monthly('2021-01-31', '2021-12-31', null, 31, OverflowMode::NoOverflow);
// after — anchor day only with AnchorDay mode
$period = CarbonPeriod::monthly('2021-01-31', '2021-12-31', null, 31);
// or keep the mode and drop the anchor
$period = CarbonPeriod::monthly('2021-01-31', '2021-12-31', null, null, OverflowMode::NoOverflow); Defensive patterns
Strategy: validation
Validate before calling
if ($anchorDay !== null && $mode !== \Carbon\Enums\OverflowMode::AnchorDay) {
throw new InvalidArgumentException(
'anchorDay may only be combined with OverflowMode::AnchorDay'
);
}
$period = CarbonPeriod::monthly($start, $end, $recurrences, $anchorDay, $mode); Prevention
- Use named arguments for monthly()/quarterly()/yearly() so $recurrences, $anchorDay and $mode cannot shift positions
- Keep a single source of truth for schedule config; forbid configs that set both anchor_day and overflow mode
When it happens
Trigger: CarbonPeriod::monthly($start, $end, null, 31, OverflowMode::NoOverflow); the same with OverflowMode::Overflow — any cycle-constructor call where the 4th argument is non-null while $mode is not OverflowMode::AnchorDay.
Common situations: Refactoring a monthly/quarterly/yearly billing or reminder schedule and carrying the anchor-day argument over while switching the overflow strategy; positional-argument mistakes where a value meant for $recurrences lands in $anchorDay.
Related errors
- You must specify $end or $recurrences but not both
- Argument 1 passed to {$class}::{$method}() must be an instan
- Invalid ISO 8601 specification: {$iso}.
- Invalid constructor parameters.
- $name
AI-assisted analysis of briannesbitt/Carbon@b13f05955d (2026-08-17).
Data as JSON: /api/errors/8b9f73e1a08cfe0f.
Report an issue: GitHub.