{"record":{"id":"b72add3dc0a2dd57","repo":"briannesbitt/Carbon","slug":"anchorday-can-be-set-only-overflow-overflowmod","errorCode":null,"errorMessage":"$anchorDay can be set only $overflow = OverflowMode::AnchorDay","messagePattern":"\\$anchorDay can be set only \\$overflow = OverflowMode::AnchorDay","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Carbon/Traits/Units.php","lineNumber":623,"sourceCode":"\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 {\n        if ($anchorDay !== null) {\n            $overflow ??= OverflowMode::AnchorDay;\n\n            if ($overflow !== OverflowMode::AnchorDay) {\n                throw new InvalidArgumentException(\n                    '$anchorDay can be set only $overflow = OverflowMode::AnchorDay',\n                );\n            }\n        }\n\n        return match ($overflow) {\n            true => OverflowMode::Overflow,\n            false => OverflowMode::NoOverflow,\n            default => $overflow,\n        };\n    }\n\n    private function shouldUnitOverflow(string $unit): bool\n    {\n        $ucUnit = ucfirst($unit).'s';\n\n        return $this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}();\n    }","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/Traits/Units.php#L605-L641","documentation":"getOverflowMode() resolves the overflow parameter shared by addUnit/add/sub: passing anchorDay implicitly selects OverflowMode::AnchorDay behavior, and if you simultaneously pass an explicit overflow (true, false, OverflowMode::Overflow or NoOverflow) the two instructions contradict each other and InvalidArgumentException is thrown. Only anchorDay + null/AnchorDay overflow, or overflow without anchorDay, are consistent states.","triggerScenarios":"->addUnit('month', 1, overflow: true, anchorDay: 31); ->add(1, 'quarter', false, 15); ->addUnit('month', 1, OverflowMode::NoOverflow, anchorDay: 31); refactors that started passing anchorDay but left an old positional bool overflow argument in place; factories forwarding both parameters from callers unaware of the constraint.","commonSituations":"Adding anchorDay to legacy call sites that already passed overflow positionally (the bool silently occupies the overflow slot and now conflicts); wrappers/builders exposing both knobs and forwarding them verbatim; copy-pasting OverflowMode::Overflow from adjacent non-anchor calls.","solutions":["Drop the explicit overflow argument when using anchorDay - anchor mode already implies no-overflow clamping","If you must pass it, pass the exact value OverflowMode::AnchorDay","Rewrite positional calls with named arguments to stop the bool and anchorDay from colliding (anchorDay: 31 makes the intent unambiguous)","In shared helpers, resolve the conflict yourself: forward overflow only when anchorDay is null"],"exampleFix":"// before\n$date->addUnit('month', 1, false, 31);\n\n// after\n$date->addUnit('month', 1, anchorDay: 31);","handlingStrategy":"validation","validationCode":"// Forward overflow only when no anchor is requested - the two options conflict\nreturn $this->base->addUnit(\n    $unit,\n    $value,\n    $anchorDay !== null ? OverflowMode::AnchorDay : $overflow,\n    $anchorDay,\n);","typeGuard":"function resolvesToConsistentOptions(OverflowMode|bool|null $overflow, ?int $anchorDay): bool\n{\n    return $anchorDay === null\n        || $overflow === null\n        || $overflow === OverflowMode::AnchorDay;\n}","tryCatchPattern":"try {\n    $date->addUnit('month', 1, $overflow, $anchorDay);\n} catch (\\InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), 'AnchorDay')) {\n        $date->addUnit('month', 1, anchorDay: $anchorDay); // drop conflicting overflow\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Use named arguments (anchorDay: 31) so positional bools cannot collide with the anchor slot","Pick one strategy per call site: either an overflow mode or an anchor day, never both","In generic wrappers, resolve the conflict before forwarding instead of passing both through"],"tags":["php","carbon","argument-validation","overflow-mode","api-misuse"],"backgroundTag":"conflicting-arguments","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}