Skip to content

/errors/python/valueerror-math-domain-error

ValueError: math domain error

verified onenvironmentlocal · linux 6.18.44-fc-v153 x64 · GNU bash 5.2.21 · Python 3.11.17updated
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

bash
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
bash
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

FunctionAcceptsFails for
math.sqrt(x)x >= 0negative numbers
math.log(x), log2, log10x > 0zero and negative numbers
math.acos(x), math.asin(x)-1 <= x <= 1anything outside that range
math.atanh(x)-1 < x < 1-1, 1 and beyond
math.factorial(n)integer n >= 0negative 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:

bash
python3 - <<'PY'
import math
x = 1.0000000000000002
clamped = min(1.0, max(-1.0, x))
print(math.acos(clamped))
PY

Output

0.0

Fix it

  1. Identify the call and print its argument.
  2. Decide what the program should do for out-of-range input: raise a clearer error, return None, or clamp.
  3. Guard the call, then run the failing input again to confirm the guard works.
bash
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))
PY

Output

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.

Sources