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

  1. Zero out the smaller units first, as the message says: $interval->minutes(0)->seconds(0)->hours(1.5)
  2. Express the amount in the smallest affected unit instead: CarbonInterval::minutes(90) or CarbonInterval::seconds(5400)
  3. Build from an explicit spec: CarbonInterval::make('PT2H30M')
  4. 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

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


AI-assisted analysis of briannesbitt/Carbon@b13f05955d (2026-08-17). Data as JSON: /api/errors/020afe5b49d08323. Report an issue: GitHub.