{"record":{"id":"0f4a51e13a55bd71","repo":"briannesbitt/Carbon","slug":"invalid-unit-for-real-timestamp-add-sub-unit","errorCode":null,"errorMessage":"Invalid unit for real timestamp add/sub: '$unit'","messagePattern":"Invalid unit for real timestamp add/sub: '\\$unit'","errorType":"exception","errorClass":"UnitException","httpStatus":null,"severity":"error","filePath":"src/Carbon/Traits/Units.php","lineNumber":156,"sourceCode":"                $value *= static::YEARS_PER_DECADE * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;\n\n                break;\n\n            // @call addUTCUnit\n            case 'century':\n                $value *= static::YEARS_PER_CENTURY * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;\n\n                break;\n\n            // @call addUTCUnit\n            case 'millennium':\n                $value *= static::YEARS_PER_MILLENNIUM * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;\n\n                break;\n\n            default:\n                if ($this->isLocalStrictModeEnabled()) {\n                    throw new UnitException(\"Invalid unit for real timestamp add/sub: '$unit'\");\n                }\n\n                return $this;\n        }\n\n        $seconds = (int) $value;\n        $microseconds = (int) round(\n            (abs((float) $value) - abs($seconds)) * ($value < 0 ? -1 : 1) * static::MICROSECONDS_PER_SECOND,\n        );\n        $date = $this->setTimestamp($this->getTimestamp() + $seconds);\n\n        return $microseconds ? $date->addUTCUnit('microsecond', $microseconds) : $date;\n    }\n\n    /**\n     * @deprecated Prefer to use add subUTCUnit() which more accurately defines what it's doing.\n     *\n     * Subtract seconds to the instance using timestamp. Positive $value travels","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/briannesbitt/Carbon/blob/b13f05955dcfd7da71d60af745fd148cbdb73505/src/Carbon/Traits/Units.php#L138-L174","documentation":"addUTCUnit()/subUTCUnit() (formerly addRealUnit) shift the raw UTC timestamp and only accept a fixed switch of units (micro/microsecond, milli/millisecond, second, minute, hour, day, week, month, quarter, year, decade, century, millennium - all as fixed 365-day approximations). An unmatched unit reaches the default branch: with strict mode enabled it throws UnitException; with strict mode off it silently returns the unchanged instance. The throw exists so that silent no-ops become visible when the app opts into strictness.","triggerScenarios":"Carbon::now()->addUTCUnit('hourss', 3) typo; ->subUTCUnit('businessDay', 1) with a domain-specific unit; a dynamic unit string from config reaching a UTC add path; enabling strict mode (Carbon 3 strict mode is on by default, or via settings/local strict flag) on code that previously relied on the silent skip; legacy calls to the deprecated addRealUnit() alias with a unit not in the switch.","commonSituations":"Typo in a unit literal; refactoring calendar-aware addUnit() calls to timestamp-based addUTCUnit() and assuming the unit sets are identical (weekday, for example, has no UTC case); turning strict mode on globally during a cleanup and uncovering previously swallowed units; unit strings built by concatenation.","solutions":["Use a unit from the accepted switch list (microsecond, millisecond, second, minute, hour, day, week, month, quarter, year, decade, century, millennium; 'micro'/'milli' aliases allowed)","If the unit is calendar-sensitive (weekday, business days), use addUnit()/add() instead of addUTCUnit()","Whitelist dynamic units before the call, mapping unknown values to a safe default","If the old silent no-op behavior is genuinely desired, disable strict mode locally via settings(['strict_mode' => false]) on that instance, or catch UnitException"],"exampleFix":"// before\n$date->addUTCUnit('businessDay', 2);\n\n// after\n$date->addWeekday(2); // or $date->addUnit('day', 2) for plain UTC days","handlingStrategy":"type-guard","validationCode":"$utcUnits = ['micro','microsecond','milli','millisecond','second','minute','hour','day','week','month','quarter','year','decade','century','millennium'];\nif (!in_array(Carbon::singularUnit(strtolower($unit)), $utcUnits, true)\n    && !in_array(strtolower($unit), $utcUnits, true)) {\n    throw new InvalidArgumentException(\"Unit not supported for UTC arithmetic: $unit\");\n}\n$date->addUTCUnit($unit, $value);","typeGuard":"function isUTCUnit(string $unit): bool\n{\n    return in_array(strtolower($unit), [\n        'micro','microsecond','milli','millisecond','second','minute','hour',\n        'day','week','month','quarter','year','decade','century','millennium',\n    ], true);\n}","tryCatchPattern":"use Carbon\\Exceptions\\UnitException;\n\ntry {\n    $date = $date->addUTCUnit($unit, $value);\n} catch (UnitException $e) {\n    // unknown unit surfaced by strict mode - fix data or fall back\n    $date = $date->addUnit('day', $value);\n}","preventionTips":["Remember addUTCUnit uses fixed 365-day months/years - prefer addUnit for calendar-aware units","Do not assume silent-skip behavior: strict mode makes bad units throw, so validate at the boundary","Keep unit vocabulary in one enum and validate once where input enters the system"],"tags":["php","carbon","utc-arithmetic","unit-validation","strict-mode"],"backgroundTag":"invalid-time-unit","analyzedSha":"b13f05955dcfd7da71d60af745fd148cbdb73505","analyzedAt":"2026-08-17T04:40:56.953Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}