briannesbitt/Carbon · error · RuntimeException
You cannot set {$unit} to a float value as {$name} would be
Error message
You cannot set {$unit} to a float value as {$name} would be overridden, set it first to 0 explicitly if you really want to erase its value What it means
Since Carbon 3 (opt-in earlier via CarbonInterval::enableFloatSetters()), giving a CarbonInterval unit a decimal value (e.g. ->hours(1.5)) cascades the fractional remainder into the smaller units (minutes, seconds). handleDecimalPart() (src/Carbon/CarbonInterval.php:3509) walks the units y/m/d/h/i/s and refuses the cascade if any unit BELOW the one being set already holds a non-zero value, because writing the fraction would silently overwrite that stored amount.
Source
Thrown at src/Carbon/CarbonInterval.php:3537
$units = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
$upper = true;
foreach ($units as $property => $name) {
if ($name === $unit) {
$upper = false;
continue;
}
if (!$upper && $this->$property !== 0) {
throw new RuntimeException(
"You cannot set $unit to a float value as $name would be overridden, ".
'set it first to 0 explicitly if you really want to erase its value'
);
}
}
$this->add($unit, $floatValue - $base);
}
}
private function getInnerValues(): array
{
return [$this->y, $this->m, $this->d, $this->h, $this->i, $this->s, $this->f, $this->invert, $this->days];
}
private function checkStartAndEnd(): void
{
if (View on GitHub (pinned to b13f05955d)
Solutions
- Zero out the smaller units first, as the message says: $interval->minutes(0)->seconds(0)->hours(1.5)
- Express the amount in the smallest affected unit instead: CarbonInterval::minutes(90) or CarbonInterval::seconds(5400)
- Build from an explicit spec: CarbonInterval::make('PT2H30M')
- When migrating Carbon 2 code that relied on truncation, cast explicitly: $interval->hours((int) $value)
Example fix
// before
$interval = CarbonInterval::make('PT1H30M');
$interval->hours(2.5); // RuntimeException: minutes would be overridden
// after
$interval = CarbonInterval::make('PT1H30M')
->minutes(0)
->seconds(0);
$interval->hours(2.5); // 2h 30m, cascade lands on zeroed minutes
// or simply
$interval = CarbonInterval::minutes(150); Defensive patterns
Strategy: validation
Validate before calling
// $unit: 'year'|'month'|'day'|'hour'|'minute'|'second' (the unit you are about to set)
$props = ['year' => 'y', 'month' => 'm', 'day' => 'd', 'hour' => 'h', 'minute' => 'i', 'second' => 's'];
$order = array_values($props);
$pos = array_search($props[$unit], $order, true);
for ($i = $pos + 1; $i < \count($order); $i++) {
if ($interval->{$order[$i]} !== 0) {
$interval = $interval->{$order[$i]} === $order[$i] ? $interval : $interval; // no-op guard
throw new RuntimeException("Zero the {$order[$i]} unit before setting $unit to a float");
}
}
$interval = $interval->{$unit.'s'}(1.5); Try / catch
try {
$interval->hours(1.5);
} catch (\RuntimeException $e) {
// message contains 'would be overridden': rebuild from a total instead
$interval = CarbonInterval::minutes((int) round($interval->totalMinutes));
} Prevention
- Set larger units before smaller ones when any value is fractional
- Prefer building intervals from ISO spec strings or the smallest target unit over mixing decimals into populated intervals
- When migrating from Carbon 2, audit unit setters for float arguments: they no longer truncate silently
When it happens
Trigger: Calling a unit setter with a real decimal part on an interval whose smaller units are already populated: CarbonInterval::make('PT1H30M')->hours(2.5) (minutes=30 would be overridden), CarbonInterval::create(0, 0, 0, 1, 30)->hours(1.5), or ->years(1.5) on an interval that already has months/days set. Only fires when float setters are enabled and the value is not a whole number.
Common situations: Upgrading Carbon 2 to 3 where floats used to be silently truncated and now cascade; building intervals from user input containing decimals; setting smaller units before larger ones when the larger one is fractional; re-using an interval parsed from an ISO spec string and then assigning a float to an upper unit.
Related errors
- Invalid interval.
- 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/020afe5b49d08323.
Report an issue: GitHub.