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

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.