{"record":{"id":"a30a7b9473bd5af5","repo":"briannesbitt/Carbon","slug":"invalid-end-date","errorCode":null,"errorMessage":"Invalid end date.","messagePattern":"Invalid end date\\.","errorType":"exception","errorClass":"InvalidPeriodDateException","httpStatus":null,"severity":"error","filePath":"src/Carbon/CarbonPeriod.php","lineNumber":1397,"sourceCode":"        $self->syncNativePeriod();\n\n        return $self;\n    }\n\n    /**\n     * Change the period end date.\n     *\n     * @param DateTime|DateTimeInterface|string|null $date\n     * @param bool|null                              $inclusive\n     *\n     * @throws \\InvalidArgumentException\n     *\n     * @return static\n     */\n    public function setEndDate(mixed $date, ?bool $inclusive = null): static\n    {\n        if ($date !== null && !$this->isInfiniteDate($date) && !$date = ([$this->dateClass, 'make'])($date, $this->timezone)) {\n            throw new InvalidPeriodDateException('Invalid end date.');\n        }\n\n        // ::make() is responsible for converting strings to DateTimeInterface objects\n        \\assert(!\\is_string($date));\n\n        $self = $this->copyIfImmutable();\n\n        if (!$date) {\n            $self = $self->removeFilter(static::END_DATE_FILTER);\n            $self->syncNativePeriod();\n\n            return $self;\n        }\n\n        \\assert($date instanceof DateTimeInterface);\n\n        $self->endDate = $date;\n","sourceCodeStart":1379,"sourceCodeEnd":1415,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/CarbonPeriod.php#L1379-L1415","documentation":"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.","triggerScenarios":"->setEndDate('foo'); ->setEndDate('2021-02-31'); ->setEndDate($emptyString) — any value Carbon cannot parse into a date (null excepted).","commonSituations":"'To' fields in reports left half-filled; date strings with locale month names; trailing whitespace/newlines from CSV or spreadsheets breaking parse.","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"],"exampleFix":"// before\n$period->setEndDate($request->input('to', '')); // '' -> Invalid end date\n\n// after\n$to = trim((string) $request->input('to', ''));\n$period->setEndDate($to === '' ? null : Carbon::parse($to));","handlingStrategy":"validation","validationCode":"if ($date !== null && \\is_string($date) && Carbon::make($date) === null) {\n    throw new InvalidArgumentException('Unparseable end date: '.$date);\n}\n$period->setEndDate($date); // null is valid and removes the end bound","typeGuard":null,"tryCatchPattern":"try {\n    $period->setEndDate($input);\n} catch (\\Carbon\\Exceptions\\InvalidPeriodDateException $e) {\n    throw new ValidationException('end: must be a valid date', 0, $e);\n}","preventionTips":["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"],"tags":["carbon","carbon-period","date-parsing","end-date"],"backgroundTag":"date-parse-error","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}