{"record":{"id":"fe5a216d01c82986","repo":"briannesbitt/Carbon","slug":"you-must-specify-end-or-recurrences-but-not-both","errorCode":null,"errorMessage":"You must specify $end or $recurrences but not both","messagePattern":"You must specify \\$end or \\$recurrences but not both","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Carbon/CarbonPeriod.php","lineNumber":582,"sourceCode":"\n        return $count ? $result : $target;\n    }\n\n    private static function getStartAndEndForCyclePeriod(\n        DateTimeInterface|string|int|null $start = null,\n        DateTimeInterface|string|int|null $end = null,\n        ?int $recurrences = null,\n        ?int $anchorDay = null,\n        OverflowMode $mode = OverflowMode::AnchorDay,\n    ): array {\n        if ($anchorDay !== null && $mode !== OverflowMode::AnchorDay) {\n            throw new InvalidArgumentException(\n                '$anchorDay parameter must not be set for $mode OverflowMode::'.$mode->name,\n            );\n        }\n\n        if ($end !== null && $recurrences !== null) {\n            throw new InvalidArgumentException(\n                'You must specify $end or $recurrences but not both',\n            );\n        }\n\n        if (\\is_int($start)) {\n            $start = CarbonImmutable::createFromTimestamp($start);\n        } elseif (\\is_string($start)) {\n            $start = CarbonImmutable::parse($start);\n        }\n\n        $start ??= CarbonImmutable::now();\n\n        if (\\is_int($end)) {\n            $end = CarbonImmutable::createFromTimestamp($end);\n        }\n\n        return [$start, $end];\n    }","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/CarbonPeriod.php#L564-L600","documentation":"The cycle constructors CarbonPeriod::monthly()/quarterly()/yearly() bound the period either by an explicit $end date or by a count of $recurrences. Supplying both is ambiguous (which bound wins?), so getStartAndEndForCyclePeriod() rejects the combination immediately (src/Carbon/CarbonPeriod.php:582).","triggerScenarios":"CarbonPeriod::monthly('2021-01-31', '2021-12-31', 12); CarbonPeriod::yearly($start, $end, 5) — any call where both $end and $recurrences are non-null.","commonSituations":"Config-driven schedules where both 'end_date' and 'occurrences' keys are set and both get forwarded; copy-pasting between create() and monthly() whose argument positions differ.","solutions":["Pass only one bound: either the end date or the recurrence count","Make the config unambiguous: when both are present, pick one (e.g. prefer the end date) before calling","Build incrementally with individually safe setters: CarbonPeriod::monthly($start)->setRecurrences(12) or ->setEndDate($end)"],"exampleFix":"// before\n$period = CarbonPeriod::monthly('2021-01-31', '2021-12-31', 12);\n\n// after — choose one bound\n$period = CarbonPeriod::monthly('2021-01-31', '2021-12-31');\n// or\n$period = CarbonPeriod::monthly('2021-01-31', null, 12);","handlingStrategy":"validation","validationCode":"if ($end !== null && $recurrences !== null) {\n    throw new InvalidArgumentException('Pass either $end or $recurrences, not both');\n}\n$period = CarbonPeriod::monthly($start, $end, $recurrences);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When reading schedule config, apply precedence explicitly (e.g. end date wins, recurrences otherwise) before calling cycle constructors","Prefer chaining ->setEndDate()/->setRecurrences() so bounds are added one at a time"],"tags":["carbon","carbon-period","argument-combination","date-range"],"backgroundTag":"invalid-argument-combination","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}