{"record":{"id":"23bde96292a6405b","repo":"TheAlgorithms/Python","slug":"number-should-not-be-negative","errorCode":null,"errorMessage":"Number should not be negative.","messagePattern":"Number should not be negative\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"dynamic_programming/factorial.py","lineNumber":19,"sourceCode":"# Factorial of a number using memoization\n\nfrom functools import lru_cache\n\n\n@lru_cache\ndef factorial(num: int) -> int:\n    \"\"\"\n    >>> factorial(7)\n    5040\n    >>> factorial(-1)\n    Traceback (most recent call last):\n      ...\n    ValueError: Number should not be negative.\n    >>> [factorial(i) for i in range(10)]\n    [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]\n    \"\"\"\n    if num < 0:\n        raise ValueError(\"Number should not be negative.\")\n\n    return 1 if num in (0, 1) else num * factorial(num - 1)\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/dynamic_programming/factorial.py#L1-L28","documentation":"Raised by factorial(num) when num < 0. Factorial is undefined for negative integers, and this recursive implementation (num * factorial(num - 1)) would recurse forever downward without the guard. The ValueError is the first thing checked on every recursive call.","triggerScenarios":"factorial(-1), factorial(-100), or any call chain where a computed argument becomes negative (e.g. factorial(n) with n from unvalidated input, or downstream arithmetic like factorial(x - y) with y > x).","commonSituations":"User input or file-parsed integers not validated for sign; combinatorics formulas that subtract in the wrong order (k > n in n-choose-k); passing a float like -3.0 also triggers it.","solutions":["Validate the argument at the boundary: if num < 0: raise/handle before calling factorial.","Fix the caller's arithmetic (e.g. clamp k to 0 <= k <= n before computing factorials of differences).","For large n, note this recursive version hits Python's recursion limit near n ~ 1000 — prefer math.factorial in production."],"exampleFix":"# before\nresult = factorial(n - k)  # negative when k > n\n\n# after\nk = min(k, n)\nresult = factorial(n - k)","handlingStrategy":"validation","validationCode":"if not isinstance(num, int) or num < 0:\n    raise ValueError('num must be a non-negative integer')\nresult = factorial(num)","typeGuard":"def is_non_negative_int(value: object) -> bool:\n    return isinstance(value, int) and not isinstance(value, bool) and value >= 0","tryCatchPattern":"try:\n    result = factorial(num)\nexcept ValueError:\n    raise ValueError(f'factorial undefined for {num!r}; check upstream arithmetic') from None","preventionTips":["Validate sign at input boundaries rather than relying on deep library checks.","In combinatorics code, clamp subtraction results (n - k) before taking factorials.","Prefer math.factorial in production; this recursive version also risks recursion limits."],"tags":["python","input-validation","recursion","math"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}