{"record":{"id":"62b05a15005e94fb","repo":"briannesbitt/Carbon","slug":"invalid-start-date","errorCode":null,"errorMessage":"Invalid start date.","messagePattern":"Invalid start date\\.","errorType":"exception","errorClass":"InvalidPeriodDateException","httpStatus":null,"severity":"error","filePath":"src/Carbon/CarbonPeriod.php","lineNumber":1369,"sourceCode":"        $self->carbonRecurrences = $recurrences === INF ? INF : (int) $recurrences;\n\n        return self::addFilterOrHandleChangedParameters($self, static::RECURRENCES_FILTER);\n    }\n\n    /**\n     * Change the period start date.\n     *\n     * @param DateTime|DateTimeInterface|string $date\n     * @param bool|null                         $inclusive\n     *\n     * @throws InvalidPeriodDateException\n     *\n     * @return static\n     */\n    public function setStartDate(mixed $date, ?bool $inclusive = null): static\n    {\n        if (!$this->isInfiniteDate($date) && !($date = ([$this->dateClass, 'make'])($date, $this->timezone))) {\n            throw new InvalidPeriodDateException('Invalid start date.');\n        }\n\n        $self = $this->copyIfImmutable();\n        $self->startDate = $date;\n\n        if ($inclusive !== null) {\n            $self = $self->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive);\n        }\n\n        $self->syncNativePeriod();\n\n        return $self;\n    }\n\n    /**\n     * Change the period end date.\n     *\n     * @param DateTime|DateTimeInterface|string|null $date","sourceCodeStart":1351,"sourceCodeEnd":1387,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/CarbonPeriod.php#L1351-L1387","documentation":"setStartDate() converts its input through the period's date class ::make(); values that cannot be parsed into a date make ::make() return null, which triggers InvalidPeriodDateException('Invalid start date.') (src/Carbon/CarbonPeriod.php:1369). Infinite markers accepted by isInfiniteDate() (INF / end-of-time style values) are exempt.","triggerScenarios":"->setStartDate('not a date'); ->setStartDate('31/02/2021'); ->setStartDate(''); ->setStartDate($garbage) where $garbage is an unparseable string or unrelated value.","commonSituations":"Free-text date fields forwarded without validation; localized or day-first formats Carbon does not guess (d/m/Y); empty request parameters coerced to empty strings.","solutions":["Validate or parse before: Carbon::hasFormat($date, 'Y-m-d') then pass, or wrap with Carbon::parse() and handle its failure","Pass a DateTimeInterface you already constructed","Reject empty/invalid input at the system boundary instead of letting the period constructor see it"],"exampleFix":"// before\n$period->setStartDate($request->input('from')); // 'whenever'\n\n// after\n$from = $request->input('from');\nif (is_string($from) && Carbon::hasFormat($from, 'Y-m-d')) {\n    $period->setStartDate(Carbon::parse($from));\n} else {\n    abort(422, 'from must be a Y-m-d date');\n}","handlingStrategy":"validation","validationCode":"if (\\is_string($date) && Carbon::make($date) === null) {\n    throw new InvalidArgumentException('Unparseable start date: '.$date);\n}\n$period->setStartDate($date);","typeGuard":null,"tryCatchPattern":"try {\n    $period->setStartDate($input);\n} catch (\\Carbon\\Exceptions\\InvalidPeriodDateException $e) {\n    throw new ValidationException('start: must be a valid date', 0, $e);\n}","preventionTips":["Constrain user input to an explicit format and validate with Carbon::hasFormat() at the boundary","Pass DateTimeInterface objects you already parsed; keep strings out of internals","Treat empty strings as missing values and convert to null/default before use"],"tags":["carbon","carbon-period","date-parsing","start-date"],"backgroundTag":"date-parse-error","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}