{"record":{"id":"068483ebc4477a8c","repo":"briannesbitt/Carbon","slug":"anchorday-must-be-greater-than-0","errorCode":null,"errorMessage":"$anchorDay must be greater than 0","messagePattern":"\\$anchorDay must be greater than 0","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Carbon/Traits/Units.php","lineNumber":600,"sourceCode":"\n            return $stringValue;\n        }\n\n        if (str_contains($stringValue, 'E')) {\n            return number_format($value, 14, '.', '');\n        }\n\n        return $stringValue;\n    }\n\n    /**\n     * Set current day of the instance to the passed value if it exits in the\n     * current month, else set current day to the last day of the month.\n     */\n    public function setAnchorDay(int $anchorDay): static\n    {\n        if ($anchorDay < 1) {\n            throw new InvalidArgumentException('$anchorDay must be greater than 0');\n        }\n\n        return $this->day(min($anchorDay, $this->daysInMonth));\n    }\n\n    private static function disallowDecimalPart(mixed $value): void\n    {\n        if (((float) $value) !== ((float) (int) $value)) {\n            throw new InvalidArgumentException(\n                'Interval objects cannot be multiplied by a non-integer value.',\n            );\n        }\n    }\n\n    private function getOverflowMode(\n        OverflowMode|bool|null $overflow = null,\n        ?int $anchorDay = null,\n    ): ?OverflowMode {","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/Traits/Units.php#L582-L618","documentation":"setAnchorDay() (reached via the anchorDay parameter of addUnit/add/sub or OverflowMode::AnchorDay) pins a day-of-month that should survive month arithmetic: after adding months the result lands on min(anchorDay, daysInMonth). Day-of-month is 1-based in PHP, so any anchorDay below 1 (0 or negative) is a programming/input error and throws InvalidArgumentException before any date math runs.","triggerScenarios":"->addUnit('month', 1, anchorDay: 0); ->add(1, 'month', overflow: null, anchorDay: -5); anchorDay computed as $date->day - $x where the subtraction hits 0; (int) cast of unvalidated request input ('day' => '0'); an optional field defaulted through (int) null (= 0) instead of null.","commonSituations":"Off-by-one bugs when deriving the anchor from a zero-based source (JS Date.getDay, array indices, ISO week day numbers); treating 'no anchor' as 0 instead of omitting the argument; form/API input where day 0 means 'not provided' but is forwarded as an int.","solutions":["Pass null (omit anchorDay) when there is no anchor instead of 0","Coerce with max(1, $anchorDay) or reject values < 1 at the input boundary","When the source is zero-based (e.g. JS weekday), add 1 before passing","Catch InvalidArgumentException only as a last-resort guard around truly external input"],"exampleFix":"// before\n$anchor = (int) ($data['pay_day'] ?? 0);\n$date->addUnit('month', 1, anchorDay: $anchor);\n\n// after\n$anchor = isset($data['pay_day']) ? max(1, (int) $data['pay_day']) : null;\n$date->addUnit('month', 1, anchorDay: $anchor);","handlingStrategy":"validation","validationCode":"$anchorDay = $data['pay_day'] ?? null;\n$anchorDay = $anchorDay === null ? null : max(1, min(31, (int) $anchorDay));\n$date->addUnit('month', 1, anchorDay: $anchorDay);","typeGuard":"function isValidAnchorDay(mixed $value): bool\n{\n    return $value === null || (is_int($value) && $value >= 1 && $value <= 31);\n}","tryCatchPattern":"try {\n    $date->addUnit('month', 1, anchorDay: $anchor);\n} catch (\\InvalidArgumentException $e) {\n    // only reachable with unvalidated external input - map to 422\n    throw new ValidationException($e->getMessage());\n}","preventionTips":["Use null for 'no anchor', never 0 - day-of-month is 1-based","When converting zero-based sources (JS weekdays, indices), add 1 before passing","Cast optional inputs with isset + (int), not (int) on a possibly-null value"],"tags":["php","carbon","argument-validation","anchor-day","off-by-one"],"backgroundTag":"argument-out-of-range","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}