briannesbitt/Carbon · error · InvalidPeriodParameterException

Invalid constructor parameters.

Error message

Invalid constructor parameters.

What it means

The CarbonPeriod constructor (and create()) sorts its variadic arguments by type: DateInterval/CarbonInterval become the interval, DateTimeInterface objects become start then end, non-negative int/float become recurrences, int/null become the options bitmask, DateTimeZone or a timezone-name string become the timezone, other strings are tried as ISO specs or dates. An argument matching none of these categories is unusable and throws InvalidPeriodParameterException (src/Carbon/CarbonPeriod.php:808).

Source

Thrown at src/Carbon/CarbonPeriod.php:808

            } elseif (!isset($sortedArguments['start']) && $parsedDate = $this->makeDateTime($argument)) {
                $sortedArguments['start'] = $parsedDate;
                $originalArguments['start'] = $argument;
            } elseif (!isset($sortedArguments['end']) && ($parsedDate = $parsedDate ?? $this->makeDateTime($argument))) {
                $sortedArguments['end'] = $parsedDate;
                $originalArguments['end'] = $argument;
            } elseif (!isset($sortedArguments['recurrences']) &&
                !isset($sortedArguments['end']) &&
                (\is_int($argument) || \is_float($argument))
                && $argument >= 0
            ) {
                $sortedArguments['recurrences'] = $argument;
            } elseif (!$optionsSet && (\is_int($argument) || $argument === null)) {
                $optionsSet = true;
                $sortedArguments['options'] = (((int) $this->options) | ((int) $argument));
            } elseif ($parsedTimezone = self::makeTimezone($argument)) {
                $sortedArguments = $this->configureTimezone($parsedTimezone, $sortedArguments, $originalArguments);
            } else {
                throw new InvalidPeriodParameterException('Invalid constructor parameters.');
            }
        }

        $this->setFromAssociativeArray($sortedArguments);

        if ($this->startDate === null) {
            $dateClass = $this->dateClass;
            $this->setStartDate($dateClass::now());
        }

        if ($this->dateInterval === null) {
            $this->setDateInterval(CarbonInterval::day());

            $this->isDefaultInterval = true;
        }

        if ($this->options === null) {
            $this->setOptions(0);

View on GitHub (pinned to b13f05955d)

Solutions

  1. Pass recognized types only: parseable date strings, DateTimeInterface, DateInterval/CarbonInterval, non-negative numbers, DateTimeZone
  2. Spread parameter arrays: CarbonPeriod::create(...$args), not create($args)
  3. Sanitize at the boundary: convert input to Carbon::parse()/CarbonInterval::make() results before the constructor sees them

Example fix

// before
$period = new CarbonPeriod($params); // $params is an array -> Invalid constructor parameters

// after
$period = CarbonPeriod::create(...$params);

// before
$period = CarbonPeriod::create($userInput); // 'garbage'
// after
$period = CarbonPeriod::create(Carbon::parse($userInput));
Defensive patterns

Strategy: validation

Validate before calling

foreach ($arguments as $argument) {
    $ok = $argument instanceof DateTimeInterface
        || $argument instanceof DateInterval
        || $argument instanceof DateTimeZone
        || \is_string($argument)
        || (\is_int($argument) || \is_float($argument)) && $argument >= 0
        || $argument === null;
    if (!$ok) {
        throw new InvalidArgumentException('Unsupported CarbonPeriod argument: '.get_debug_type($argument));
    }
}
$period = CarbonPeriod::create(...$arguments);

Try / catch

try {
    $period = CarbonPeriod::create(...$args);
} catch (\Carbon\Exceptions\InvalidPeriodParameterException $e) {
    // surface as a 422 to the caller instead of a 500
    throw new ValidationException('Invalid period parameters', 0, $e);
}

Prevention

When it happens

Trigger: new CarbonPeriod('garbage'); new CarbonPeriod(-1) (negative numbers have no slot); new CarbonPeriod(true); new CarbonPeriod(['2021-01-01', '2021-03-01']) passed as one array instead of spread; new CarbonPeriod($unrelatedObject).

Common situations: Forwarding unvalidated user input straight into create(...$params); a null-ish variable silently becoming a bool; forgetting to spread an array of prepared arguments; passing a value object instead of a DateTime.

Related errors


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