{"record":{"id":"c008e0f088b7c979","repo":"briannesbitt/Carbon","slug":"could-not-find-next-valid-date","errorCode":null,"errorMessage":"Could not find next valid date.","messagePattern":"Could not find next valid date\\.","errorType":"exception","errorClass":"UnreachableException","httpStatus":null,"severity":"error","filePath":"src/Carbon/CarbonPeriod.php","lineNumber":2651,"sourceCode":"    /**\n     * Keep incrementing the current date until a valid date is found or the iteration is ended.\n     *\n     * @throws RuntimeException\n     */\n    protected function incrementCurrentDateUntilValid(): void\n    {\n        $attempts = 0;\n\n        do {\n            $this->carbonCurrent = $this->carbonCurrent->add(\n                $this->dateInterval,\n                $this->dateInterval->getStep() && $this->dateInterval->invert ? -1 : 1,\n            );\n\n            $this->validationResult = null;\n\n            if (++$attempts > static::NEXT_MAX_ATTEMPTS) {\n                throw new UnreachableException('Could not find next valid date.');\n            }\n        } while ($this->validateCurrentDate() === false);\n    }\n\n    /**\n     * Call given macro.\n     */\n    protected function callMacro(string $name, array $parameters): mixed\n    {\n        $macro = static::$macros[$name];\n\n        if ($macro instanceof Closure) {\n            $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);\n\n            return ($boundMacro ?: $macro)(...$parameters);\n        }\n\n        return $macro(...$parameters);","sourceCodeStart":2633,"sourceCodeEnd":2669,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/CarbonPeriod.php#L2633-L2669","documentation":"While iterating, CarbonPeriod advances the current date by the interval and re-validates it against the filters. If no candidate passes validation within NEXT_MAX_ATTEMPTS (1000) attempts, the iterator concludes the filters may never be satisfied and throws UnreachableException('Could not find next valid date.') instead of spinning forever (src/Carbon/CarbonPeriod.php:2651).","triggerScenarios":"A filter that can never match: ->filter(fn ($date) => false); stepping P1W from a Monday while filtering ->isSunday() (the weekday never changes); a filter looking for an impossible date (Feb 30); a filter whose condition is expressed in the wrong direction for an inverted interval.","commonSituations":"Filter logic bugs (wrong comparison operator, inverted condition); misaligned start date combined with a weekly interval and a weekday filter; filter units that never coincide with the interval step; schedule generators fed impossible requirements.","solutions":["Align the start with the filter: start on a matching date, e.g. ->setStartDate($start->next(Carbon::SUNDAY)) before a isSunday filter with P1W","Fix the filter so dates reachable by the interval can satisfy it, and unit-test it against a sample of candidates","Step by a unit that can reach a match (P1D instead of P1W) and end iteration explicitly by returning CarbonPeriod::END_ITERATION from the filter when done"],"exampleFix":"// before\n$period = CarbonPeriod::create('2021-01-04', 'P1W') // 2021-01-04 is a Monday\n    ->filter(fn ($date) => $date->isSunday());\n$period->next(); // Could not find next valid date\n\n// after\n$period = CarbonPeriod::create('2021-01-10', 'P1W') // a Sunday\n    ->filter(fn ($date) => $date->isSunday());","handlingStrategy":"try-catch","validationCode":"// Smoke-test the filter over the next candidates reachable by the interval\n$probe = $period->getStartDate()->copy();\n$satisfiable = false;\nfor ($i = 0; $i < 1000; $i++) {\n    if ($filter($probe, false)) { $satisfiable = true; break; }\n    $probe = $probe->add($period->getDateInterval());\n}\nif (!$satisfiable) {\n    throw new InvalidArgumentException('Filter can never match the interval step');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $period->next(); // or foreach ($period as $date)\n} catch (\\Carbon\\Exceptions\\UnreachableException $e) {\n    // filters and interval can never converge: abort schedule generation and report\n    \\Log::warning('Unsatisfiable period filter: '.$e->getMessage());\n    return [];\n}","preventionTips":["Align the period start with the filter (start on a date the filter accepts)","Unit-test filters against a sample window of real candidates before deploying schedules","Make sure the interval step can actually reach dates the filter accepts (P1W preserves weekday; P1D reaches everything)","Use CarbonPeriod::END_ITERATION inside filters to stop iteration deliberately"],"tags":["carbon","carbon-period","filters","infinite-loop-guard","iteration"],"backgroundTag":"unsatisfiable-filter","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}