{"record":{"id":"9790015e00d87773","repo":"briannesbitt/Carbon","slug":"empty-interval-is-not-accepted","errorCode":null,"errorMessage":"Empty interval is not accepted.","messagePattern":"Empty interval is not accepted\\.","errorType":"exception","errorClass":"InvalidIntervalException","httpStatus":null,"severity":"error","filePath":"src/Carbon/CarbonPeriod.php","lineNumber":994,"sourceCode":"     *\n     * @return static\n     */\n    public function setDateInterval(mixed $interval, Unit|string|null $unit = null): static\n    {\n        if ($interval instanceof Unit) {\n            $interval = $interval->interval();\n        }\n\n        if ($unit instanceof Unit) {\n            $unit = $unit->name;\n        }\n\n        if (!$interval = CarbonInterval::make($interval, $unit)) {\n            throw new InvalidIntervalException('Invalid interval.');\n        }\n\n        if ($interval->spec() === 'PT0S' && !$interval->f && !$interval->getStep()) {\n            throw new InvalidIntervalException('Empty interval is not accepted.');\n        }\n\n        $self = $this->copyIfImmutable();\n        $self->dateInterval = $interval;\n\n        $self->isDefaultInterval = false;\n\n        $self->handleChangedParameters();\n\n        return $self;\n    }\n\n    /**\n     * Reset the date interval to the default value.\n     *\n     * Difference with simply setting interval to 1-day is that P1D will not appear when calling toIso8601String()\n     * and also next adding to the interval won't include the default 1-day.\n     */","sourceCodeStart":976,"sourceCodeEnd":1012,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/CarbonPeriod.php#L976-L1012","documentation":"A period must advance by a non-zero amount. After conversion, setDateInterval() rejects intervals whose specification is exactly 'PT0S' with no fractional seconds (f) and no step, because iterating a zero interval would never move and spin forever (src/Carbon/CarbonPeriod.php:994).","triggerScenarios":"->setDateInterval(0); ->setDateInterval('PT0S'); ->setDateInterval(CarbonInterval::minutes(0)); a computed interval that happens to be zero, e.g. ->setDateInterval($start->diffAsCarbonInterval($end)) when both dates are identical.","commonSituations":"Intervals derived from user-chosen date pairs that can be equal; dividing a duration by a count that rounds to 0; placeholder/test intervals of 0.","solutions":["Guard computed intervals: if the amount is 0, reject the input or default to a sensible unit","Use a real step: 'P1D', 'PT1S', or the integer 1","If sub-second stepping was intended, give the interval a step or microsecond fraction: CarbonInterval::milliseconds(500) or ->stepBy()? use a non-empty spec such as 'PT0.5S'"],"exampleFix":"// before\n$diff = $start->diffAsCarbonInterval($end); // can be PT0S\n$period->setDateInterval($diff); // Empty interval is not accepted\n\n// after\n$diff = $start->diffAsCarbonInterval($end);\nif ($diff->isEmpty()) {\n    throw new InvalidArgumentException('Start and end must differ');\n}\n$period->setDateInterval($diff);","handlingStrategy":"validation","validationCode":"$made = CarbonInterval::make($input);\nif ($made === null || ($made->spec() === 'PT0S' && !$made->f && !$made->getStep())) {\n    throw new InvalidArgumentException('Interval must be non-zero');\n}\n$period->setDateInterval($made);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When intervals are computed (diff between dates), always handle the equal-dates case before passing them","Treat a zero interval as invalid input in your own validation layer, not as an empty period"],"tags":["carbon","carbon-period","interval","zero-value","infinite-loop-guard"],"backgroundTag":"zero-interval-rejected","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}