/errors/python/valueerror-math-domain-error
ValueError: math domain error
- tool
- Python
- exit code
- 1
- versions
- Python 3.x
- os
- any
ValueError: math domain error means a function from the math module received a number that is outside the set of values it accepts, called its domain. The classic cases are math.sqrt() of a negative number and math.log() of zero or a negative number. Check the argument before the call, or switch to cmath when a complex result is fine.
Reproduce it
python3 -c 'import math; print(math.sqrt(-1))'Output · exit 1
Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: math domain error
python3 -c 'import math; print(math.log(0))'Output · exit 1
Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: math domain error
The traceback ends with the same line for both: the message does not say which argument was wrong, so read the call in the line above it.
Which functions have a restricted domain
| Function | Accepts | Fails for |
|---|---|---|
math.sqrt(x) | x >= 0 | negative numbers |
math.log(x), log2, log10 | x > 0 | zero and negative numbers |
math.acos(x), math.asin(x) | -1 <= x <= 1 | anything outside that range |
math.atanh(x) | -1 < x < 1 | -1, 1 and beyond |
math.factorial(n) | integer n >= 0 | negative integers (a different ValueError message) |
The documentation of each function lists its domain. Not every restricted call raises this message: some report a different ValueError or an OverflowError.
Cause 1: negative input from a calculation
A value that should never be negative can become so through a bug, bad data or rounding. A distance formula math.sqrt(a - b) fails as soon as b is larger than a. Print the argument just before the call to see which value reached it.
Cause 2: floating-point drift
Mathematically valid values can leave the domain by a tiny amount. Normalising vectors and computing an angle with acos(dot) is the usual place:
python3 - <<'PY'
import math
x = 1.0000000000000002
clamped = min(1.0, max(-1.0, x))
print(math.acos(clamped))
PYOutput
0.0
Fix it
- Identify the call and print its argument.
- Decide what the program should do for out-of-range input: raise a clearer error, return
None, or clamp. - Guard the call, then run the failing input again to confirm the guard works.
python3 - <<'PY'
import math, cmath
def safe_sqrt(x):
return math.sqrt(x) if x >= 0 else float("nan")
print(safe_sqrt(-4))
print(cmath.sqrt(-4))
PYOutput
nan 2j
Prevent it
Validate inputs at the boundary of the program, not at every call. Prefer math.isclose() over == for float comparisons, and use numpy on arrays when nan is an acceptable result: it warns instead of stopping the run. A related arithmetic failure with a different message is ZeroDivisionError.
FAQ
Why does math.sqrt(-1) raise an error instead of returning a complex number?
The math module works with real numbers only and raises ValueError outside the real domain. The cmath module is the complex version: cmath.sqrt(-1) returns 1j.
What is the math domain of log?
The real logarithm is defined only for numbers greater than zero. math.log(0) and math.log(-5) both raise ValueError: math domain error.
Why do I get the error for a value that looks valid, such as 1.0000000000000002?
Floating-point rounding. A cosine or dot product that should be exactly 1 can come out a few units in the last place above it, and acos rejects it. Clamp the value to -1.0 .. 1.0 before the call.