ValueError: math domain error (tested)
ValueError: math domain error means a math function got an input with no real-number answer. We ran every common trigger on Python 3.13.5, including the one that catches careful code: a value that should be exactly 1 but rounds to just above it.
1. Which calls raise it
import math
for expr in ["math.sqrt(-1)", "math.log(0)", "math.log(-5)", "math.log10(0)",
"math.acos(1.0000000000000002)", "math.asin(-1.5)",
"math.pow(-8, 1/3)", "math.atanh(1)", "math.sqrt(-0.0)"]:
try:
print(f"{expr} = {eval(expr)!r}")
except ValueError as e:
print(f"{expr}: {e}")
math.sqrt(-1): math domain error
math.log(0): math domain error
math.log(-5): math domain error
math.log10(0): math domain error
math.acos(1.0000000000000002): math domain error
math.asin(-1.5): math domain error
math.pow(-8, 1/3): math domain error
math.atanh(1): math domain error
math.sqrt(-0.0) = -0.0
Measured: every one of these gives the identical message, math domain error, with no hint of which argument was bad, so in a long formula add a check or print before each call. The rule is the same in each case: the real-number result doesn't exist. sqrt of a negative, log/log10 of zero or a negative, acos/asin outside [-1, 1], atanh at ±1, and math.pow of a negative base with a fractional exponent. math.sqrt(-0.0) is fine and returns -0.0.
2. The one that surprises people: float rounding just past 1
import math
a = [0.1, 0.2, 1.1]
b = [0.1, 0.2, 1.1] # same vector: the angle should be 0
dot = sum(x * y for x, y in zip(a, b))
norm = math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b))
cos = dot / norm
print(repr(cos))
try:
print(math.acos(cos))
except ValueError as e:
print("acos:", e)
print(math.acos(max(-1.0, min(1.0, cos))))
1.0000000000000002
acos: math domain error
0.0
Measured: the cosine of a vector with itself should be exactly 1.0, but floating-point rounding produced 1.0000000000000002 and acos refused it. This is the usual cause in cosine similarity, angle between vectors, and great-circle distance (haversine) code: inputs that are mathematically fine but numerically a hair outside the domain. Clamp to [-1, 1] right before the call, as in the last line. Only clamp where rounding is the explanation; a value like 1.5 is a real bug and clamping hides it.
3. When you actually want the answer for a negative
import cmath, math
print(cmath.sqrt(-1))
print((-8) ** (1/3))
print(-(8 ** (1/3)))
print(math.cbrt(-8))
print(-8 ** 2, (-8) ** 2)
1j
(1.0000000000000002+1.7320508075688772j)
-2.0
-2.0
-64 64
Measured: cmath.sqrt(-1) returns 1j if you need complex results. The ** operator doesn't raise for a negative base with a fractional exponent; it silently returns a complex number ((-8) ** (1/3) gave 1.0000000000000002+1.7320508075688772j, not -2), which then breaks later in your code instead. For a real cube root use math.cbrt(-8) (Python 3.11+) or -(8 ** (1/3)). Also watch precedence: -8 ** 2 is -64, because ** binds tighter than the minus sign.
4. Fix checklist
- Find the call: the traceback line tells you which function; print its argument just before it.
- Negative into
sqrt/log: usually a sign bug or a subtraction in the wrong order upstream. Fix the cause; useabs()only if a negative really means the same thing. log(0): guard empty or zero inputs (if x > 0), or add a small offset only if your formula is defined that way (for examplelog1p).acos/asinon computed values: clamp withmax(-1.0, min(1.0, x)).
Frequently asked questions
What causes ValueError: math domain error?
A math function got an input where no real result exists. We measured it from math.sqrt(-1), math.log(0), math.log(-5), math.log10(0), math.acos(1.0000000000000002), math.asin(-1.5), math.pow(-8, 1/3) and math.atanh(1).
Why does math.acos fail when the value should be 1?
Float rounding. We measured the cosine of a vector with itself coming out as 1.0000000000000002, which acos rejects. Clamp with max(-1.0, min(1.0, x)) before calling it.
How do I take the square root of a negative number in Python?
Use cmath.sqrt(), which returns a complex number; we measured cmath.sqrt(-1) giving 1j.
Why does (-8) ** (1/3) not return -2?
With a negative base and fractional exponent, ** returns a complex number instead of raising; we measured 1.0000000000000002+1.7320508075688772j. Use math.cbrt(-8) on Python 3.11+, which returned -2.0.
Does math.log(0) return -inf?
No, math.log(0) raises ValueError: math domain error. Check for zero before the call.
Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5's math and cmath modules: sqrt, log, log10, acos, asin, atanh and pow at and past their domain edges, a cosine-similarity calculation that rounds to 1.0000000000000002, and the ** operator and math.cbrt with negative bases. Every code block was run verbatim and its output pasted from that run. PlainHeaders is our extension; math and cmath are built in.