briannesbitt/Carbon · error · InvalidArgumentException
$anchorDay can be set only $overflow = OverflowMode::AnchorD
Error message
$anchorDay can be set only $overflow = OverflowMode::AnchorDay
What it means
getOverflowMode() resolves the overflow parameter shared by addUnit/add/sub: passing anchorDay implicitly selects OverflowMode::AnchorDay behavior, and if you simultaneously pass an explicit overflow (true, false, OverflowMode::Overflow or NoOverflow) the two instructions contradict each other and InvalidArgumentException is thrown. Only anchorDay + null/AnchorDay overflow, or overflow without anchorDay, are consistent states.
Source
Thrown at src/Carbon/Traits/Units.php:623
private static function disallowDecimalPart(mixed $value): void
{
if (((float) $value) !== ((float) (int) $value)) {
throw new InvalidArgumentException(
'Interval objects cannot be multiplied by a non-integer value.',
);
}
}
private function getOverflowMode(
OverflowMode|bool|null $overflow = null,
?int $anchorDay = null,
): ?OverflowMode {
if ($anchorDay !== null) {
$overflow ??= OverflowMode::AnchorDay;
if ($overflow !== OverflowMode::AnchorDay) {
throw new InvalidArgumentException(
'$anchorDay can be set only $overflow = OverflowMode::AnchorDay',
);
}
}
return match ($overflow) {
true => OverflowMode::Overflow,
false => OverflowMode::NoOverflow,
default => $overflow,
};
}
private function shouldUnitOverflow(string $unit): bool
{
$ucUnit = ucfirst($unit).'s';
return $this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}();
}View on GitHub (pinned to b13f05955d)
Solutions
- Drop the explicit overflow argument when using anchorDay - anchor mode already implies no-overflow clamping
- If you must pass it, pass the exact value OverflowMode::AnchorDay
- Rewrite positional calls with named arguments to stop the bool and anchorDay from colliding (anchorDay: 31 makes the intent unambiguous)
- In shared helpers, resolve the conflict yourself: forward overflow only when anchorDay is null
Example fix
// before
$date->addUnit('month', 1, false, 31);
// after
$date->addUnit('month', 1, anchorDay: 31); Defensive patterns
Strategy: validation
Validate before calling
// Forward overflow only when no anchor is requested - the two options conflict
return $this->base->addUnit(
$unit,
$value,
$anchorDay !== null ? OverflowMode::AnchorDay : $overflow,
$anchorDay,
); Type guard
function resolvesToConsistentOptions(OverflowMode|bool|null $overflow, ?int $anchorDay): bool
{
return $anchorDay === null
|| $overflow === null
|| $overflow === OverflowMode::AnchorDay;
} Try / catch
try {
$date->addUnit('month', 1, $overflow, $anchorDay);
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'AnchorDay')) {
$date->addUnit('month', 1, anchorDay: $anchorDay); // drop conflicting overflow
} else {
throw $e;
}
} Prevention
- Use named arguments (anchorDay: 31) so positional bools cannot collide with the anchor slot
- Pick one strategy per call site: either an overflow mode or an anchor day, never both
- In generic wrappers, resolve the conflict before forwarding instead of passing both through
When it happens
Trigger: ->addUnit('month', 1, overflow: true, anchorDay: 31); ->add(1, 'quarter', false, 15); ->addUnit('month', 1, OverflowMode::NoOverflow, anchorDay: 31); refactors that started passing anchorDay but left an old positional bool overflow argument in place; factories forwarding both parameters from callers unaware of the constraint.
Common situations: Adding anchorDay to legacy call sites that already passed overflow positionally (the bool silently occupies the overflow slot and now conflicts); wrappers/builders exposing both knobs and forwarding them verbatim; copy-pasting OverflowMode::Overflow from adjacent non-anchor calls.
Related errors
- $anchorDay must be greater than 0
- Invalid constructor parameters.
- Unknown unit '$unit'.
- Invalid serialized value: $value
- Invalid unit for real timestamp add/sub: '$unit'
AI-assisted analysis of briannesbitt/Carbon@b13f05955d (2026-08-17).
Data as JSON: /api/errors/b72add3dc0a2dd57.
Report an issue: GitHub.