TheAlgorithms/Python · error · ValueError

Number should not be negative.

Error message

Number should not be negative.

What it means

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.

Source

Thrown at dynamic_programming/factorial.py:19

# Factorial of a number using memoization

from functools import lru_cache


@lru_cache
def factorial(num: int) -> int:
    """
    >>> factorial(7)
    5040
    >>> factorial(-1)
    Traceback (most recent call last):
      ...
    ValueError: Number should not be negative.
    >>> [factorial(i) for i in range(10)]
    [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
    """
    if num < 0:
        raise ValueError("Number should not be negative.")

    return 1 if num in (0, 1) else num * factorial(num - 1)


if __name__ == "__main__":
    import doctest

    doctest.testmod()

View on GitHub (pinned to f5988cc097)

Solutions

  1. Validate the argument at the boundary: if num < 0: raise/handle before calling factorial.
  2. Fix the caller's arithmetic (e.g. clamp k to 0 <= k <= n before computing factorials of differences).
  3. For large n, note this recursive version hits Python's recursion limit near n ~ 1000 — prefer math.factorial in production.

Example fix

# before
result = factorial(n - k)  # negative when k > n

# after
k = min(k, n)
result = factorial(n - k)
Defensive patterns

Strategy: validation

Validate before calling

if not isinstance(num, int) or num < 0:
    raise ValueError('num must be a non-negative integer')
result = factorial(num)

Type guard

def is_non_negative_int(value: object) -> bool:
    return isinstance(value, int) and not isinstance(value, bool) and value >= 0

Try / catch

try:
    result = factorial(num)
except ValueError:
    raise ValueError(f'factorial undefined for {num!r}; check upstream arithmetic') from None

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/23bde96292a6405b. Report an issue: GitHub.