briannesbitt/Carbon · error · UnsupportedUnitException

Unsupported unit '$unit'

Error message

Unsupported unit '$unit'

What it means

Inside rawAddUnit(), Carbon first builds CarbonInterval::fromString("<number> <unit>"); if that throws InvalidIntervalException it retries with DateTime::modify("<number> <unit>"). When both parsers reject the unit, UnsupportedUnitException is thrown with the unit name and the interval-parse failure chained as previous. This is the low-level 'this unit name means nothing to Carbon or PHP relative formats' signal; addUnit() normally wraps it into a broader UnitException.

Source

Thrown at src/Carbon/Traits/Units.php:569

            'minus' => $this->doMinus(...$parameters),
            default => null,
        };
    }

    private static function rawAddUnit(self $date, string $unit, int|float $value): ?static
    {
        try {
            $absoluteValue = abs($value);

            return $date->rawAdd(
                CarbonInterval::fromString(self::getNumberAsString($absoluteValue)." $unit")
                    ->invert($value < 0),
            );
        } catch (InvalidIntervalException $exception) {
            try {
                return $date->modify(self::getNumberAsString($value)." $unit");
            } catch (InvalidFormatException) {
                throw new UnsupportedUnitException($unit, previous: $exception);
            }
        }
    }

    private static function getNumberAsString(int|float $value): string
    {
        $stringValue = (string) $value;

        if ($value < -1 || $value > 1) {
            if (str_contains($stringValue, 'E')) {
                return number_format($value, 0, '.', '');
            }

            return $stringValue;
        }

        if (str_contains($stringValue, 'E')) {
            return number_format($value, 14, '.', '');

View on GitHub (pinned to b13f05955d)

Solutions

  1. Map the domain unit to a real Carbon unit before calling (businessDay -> weekday + skip logic, sprint -> N days)
  2. Use CarbonInterval::fromString() on the raw text first to validate vocabulary cheaply and early
  3. Catch UnsupportedUnitException specifically when you need to distinguish 'bad unit' from other addUnit failures (it will otherwise be re-wrapped in UnitException by addUnit)
  4. Replace free-text units with the Unit enum at your input boundary

Example fix

// before
$date->addUnit($plan->cycle_unit, 1); // 'fortnight' -> UnsupportedUnitException

// after
$map = ['fortnight' => ['day', 14], 'businessDay' => ['weekday', 1]];
[$unit, $factor] = $map[$plan->cycle_unit] ?? [$plan->cycle_unit, 1];
$date->addUnit($unit, $factor);
Defensive patterns

Strategy: type-guard

Validate before calling

try {
    CarbonInterval::fromString('1 '.strtolower((string) $unit)); // dry-run the vocabulary
} catch (InvalidIntervalException $e) {
    throw new InvalidArgumentException("Unit '$unit' is not understood");
}
// DateTime-relative fallbacks ('weekday' etc.) may still pass - keep the try/catch too

Type guard

function isSupportedIntervalUnit(string $unit): bool
{
    try {
        CarbonInterval::fromString('1 '.strtolower($unit));

        return true;
    } catch (InvalidIntervalException) {
        return false;
    }
}

Try / catch

use Carbon\Exceptions\UnsupportedUnitException;
use Carbon\Exceptions\UnitException;

try {
    $date = $date->addUnit($unit, $value);
} catch (UnitException $e) {
    if ($e->getPrevious() instanceof UnsupportedUnitException) {
        [$unit, $value] = translateDomainUnit($unit, $value); // e.g. fortnight -> 14 days
        $date = $date->addUnit($unit, $value);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: A unit only your domain understands ('businessDay', 'sprint', 'fortnight', 'payPeriod') reaching rawAddUnit; concatenated strings like 'sec'.'onds' producing 'sec onds'; calling CarbonInterval-unsupported unit through any add/sub path; empty unit resulting in a bare '3 ' string both parsers reject.

Common situations: Domain-specific duration vocabularies passed to generic helpers; renaming unit constants and missing call sites; code that assumed strtotime-compatible words ('fortnight' is not a PHP relative unit); data from spreadsheets/APIs with free-text units.

Related errors


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