briannesbitt/Carbon · error · InvalidPeriodDateException
Invalid end date.
Error message
Invalid end date.
What it means
setEndDate() converts its input through the period's date class ::make() exactly like setStartDate(); unparseable values make ::make() return null and InvalidPeriodDateException('Invalid end date.') is thrown (src/Carbon/CarbonPeriod.php:1397). Note that null is VALID here — it removes the end filter — and infinite markers (INF) are accepted.
Source
Thrown at src/Carbon/CarbonPeriod.php:1397
$self->syncNativePeriod();
return $self;
}
/**
* Change the period end date.
*
* @param DateTime|DateTimeInterface|string|null $date
* @param bool|null $inclusive
*
* @throws \InvalidArgumentException
*
* @return static
*/
public function setEndDate(mixed $date, ?bool $inclusive = null): static
{
if ($date !== null && !$this->isInfiniteDate($date) && !$date = ([$this->dateClass, 'make'])($date, $this->timezone)) {
throw new InvalidPeriodDateException('Invalid end date.');
}
// ::make() is responsible for converting strings to DateTimeInterface objects
\assert(!\is_string($date));
$self = $this->copyIfImmutable();
if (!$date) {
$self = $self->removeFilter(static::END_DATE_FILTER);
$self->syncNativePeriod();
return $self;
}
\assert($date instanceof DateTimeInterface);
$self->endDate = $date;
View on GitHub (pinned to b13f05955d)
Solutions
- Validate/parse first: Carbon::hasFormat() or try/catch around Carbon::parse()
- Pass a DateTimeInterface instance
- Pass null deliberately when you want no end bound — do not use a junk string as a sentinel
Example fix
// before
$period->setEndDate($request->input('to', '')); // '' -> Invalid end date
// after
$to = trim((string) $request->input('to', ''));
$period->setEndDate($to === '' ? null : Carbon::parse($to)); Defensive patterns
Strategy: validation
Validate before calling
if ($date !== null && \is_string($date) && Carbon::make($date) === null) {
throw new InvalidArgumentException('Unparseable end date: '.$date);
}
$period->setEndDate($date); // null is valid and removes the end bound Try / catch
try {
$period->setEndDate($input);
} catch (\Carbon\Exceptions\InvalidPeriodDateException $e) {
throw new ValidationException('end: must be a valid date', 0, $e);
} Prevention
- Normalize/trim date strings from CSV, spreadsheets and forms before passing
- Remember null is a legal 'no end' value — use it instead of junk sentinels
- Validate 'from/to' pairs together in one place before building the period
When it happens
Trigger: ->setEndDate('foo'); ->setEndDate('2021-02-31'); ->setEndDate($emptyString) — any value Carbon cannot parse into a date (null excepted).
Common situations: 'To' fields in reports left half-filled; date strings with locale month names; trailing whitespace/newlines from CSV or spreadsheets breaking parse.
Related errors
- Invalid start date.
- 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/a30a7b9473bd5af5.
Report an issue: GitHub.