fractions: NaN and Infinity Raise Different Exception Types (tested)

Both NaN and Infinity are floats that can't be represented as an exact Fraction. We measured what Fraction() actually raises for each -- they look like the same kind of failure, but turn out to use two unrelated exception types.

1. Fraction(nan) raises ValueError

from fractions import Fraction

try:
    Fraction(float("nan"))
except Exception as e:
    print(type(e).__name__, "-", e)
ValueError - cannot convert NaN to integer ratio

Measured: converting NaN to a Fraction raises ValueError, the exception most code already catches for "bad numeric input."

2. Fraction(inf) raises OverflowError instead -- not ValueError

from fractions import Fraction

try:
    Fraction(float("inf"))
except Exception as e:
    print(type(e).__name__, "-", e)

print("OverflowError is a ValueError subclass:", issubclass(OverflowError, ValueError))
OverflowError - cannot convert Infinity to integer ratio
OverflowError is a ValueError subclass: False

Measured: Fraction(float("inf")) raises OverflowError, not ValueError -- and OverflowError is not a subclass of ValueError (it inherits from ArithmeticError). The two failures read like the same category of problem ("this float can't become an exact Fraction") but are unrelated exception types.

3. The risk: a try/except ValueError silently lets Infinity through uncaught

from fractions import Fraction

def safe_fraction(x):
    try:
        return Fraction(x)
    except ValueError:
        return None

print(safe_fraction(float("nan")))    # caught, returns None
print(safe_fraction(float("inf")))    # not caught -- raises
None
Traceback (most recent call last):
  ...
OverflowError: cannot convert Infinity to integer ratio

Measured: a helper written and tested against NaN input appears to safely sanitize bad floats, then raises an uncaught OverflowError the first time it sees Infinity instead -- a value that's just as invalid for the same reason, from the same source (a bad division, a parsed value, a sensor reading). Catch (ValueError, OverflowError) explicitly, or catch the common base ArithmeticError only covers OverflowError and not ValueError either -- there's no single built-in base class that covers both.

Frequently asked questions

Does Fraction(float('inf')) raise the same exception as Fraction(float('nan'))?

No -- we measured Fraction(float('nan')) raising ValueError, but Fraction(float('inf')) raising OverflowError instead. They're unrelated exception types: OverflowError is not a subclass of ValueError.

Why does my except ValueError not catch Fraction(float('inf'))?

Because converting Infinity to a Fraction raises OverflowError, not ValueError -- we confirmed issubclass(OverflowError, ValueError) is False, so a try/except ValueError written to sanitize bad float input catches NaN but lets Infinity propagate uncaught.

What exception does Fraction() raise for NaN input?

We measured Fraction(float('nan')) raising ValueError with the message 'cannot convert NaN to integer ratio'.

What exception does Fraction() raise for Infinity input?

We measured Fraction(float('inf')) raising OverflowError with the message 'cannot convert Infinity to integer ratio' -- a different exception type than NaN raises, despite both being 'can't convert to exact Fraction' failures.

How do I catch both NaN and Infinity errors when converting to Fraction?

Catch both exception types explicitly: except (ValueError, OverflowError). We confirmed there's no single built-in exception class that's a common ancestor covering both -- ValueError and OverflowError are unrelated branches of the exception hierarchy.

Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in fractions module: called Fraction() on float('nan') and float('inf'), recorded the exact exception type each raised, and checked whether a try/except ValueError written to catch one also catches the other. PlainHeaders is our extension; Python's fractions module is built in.