python/cpython · error · ValueError
Cannot convert signaling NaN to float
Error message
Cannot convert signaling NaN to float
What it means
float(Decimal('sNaN')) raises ValueError because a signaling NaN must trap on use, and conversion to float counts as a use; converting it would silently demote it to a quiet float NaN and lose the signal. Quiet NaNs convert fine to float('nan') with sign preserved.
Source
Thrown at Lib/_pydecimal.py:1570
return context._raise_error(DivisionByZero, 'x // 0',
self._sign ^ other._sign)
else:
return context._raise_error(DivisionUndefined, '0 // 0')
return self._divide(other, context)[0]
def __rfloordiv__(self, other, context=None):
"""Swaps self/other and returns __floordiv__."""
other = _convert_other(other)
if other is NotImplemented:
return other
return other.__floordiv__(self, context=context)
def __float__(self):
"""Float representation."""
if self._isnan():
if self.is_snan():
raise ValueError("Cannot convert signaling NaN to float")
s = "-nan" if self._sign else "nan"
else:
s = str(self)
return float(s)
def __int__(self):
"""Converts self to an int, truncating if necessary."""
if self._is_special:
if self._isnan():
raise ValueError("Cannot convert NaN to integer")
elif self._isinfinity():
raise OverflowError("Cannot convert infinity to integer")
s = (-1)**self._sign
if self._exp >= 0:
return s*int(self._int)*10**self._exp
else:
return s*int(self._int[:self._exp] or '0')
View on GitHub (pinned to bc6749cc3b)
Solutions
- Quiet the sNaN first if loss of signal is acceptable: q = d + 0 under a context with InvalidOperation untrapped yields quiet NaN, then float(q)
- Reject sNaN explicitly at the boundary with is_snan() and raise your own error
- Keep the pipeline in Decimal end-to-end so no float() conversion is needed
Example fix
// before
f = float(dec) # ValueError if dec is Decimal('sNaN')
// after
import math
f = math.nan if dec.is_snan() else float(dec) Defensive patterns
Strategy: validation
Validate before calling
import math
def safe_float(d):
if d.is_snan():
return math.nan # explicit policy: quiet it
return float(d) Type guard
from decimal import Decimal
def is_float_safe(d) -> bool:
return not (isinstance(d, Decimal) and d.is_snan()) Try / catch
try:
f = float(d)
except ValueError as e:
if 'signaling NaN' in str(e):
f = float('nan')
else:
raise Prevention
- Quieten sNaN immediately after parsing (d * 1 under a non-trapping context)
- Keep numeric pipelines in Decimal until the final boundary; convert once, guarded
- Distinguish is_snan() from is_nan() in validation: quiet NaN converts fine
When it happens
Trigger: float(Decimal('sNaN')); float(Decimal('sNaN123')); math.sin(Decimal('sNaN')) (implicit float conversion); json serialization code that calls float() on values.
Common situations: Parsed FIX/financial data carrying sNaN sentinels, then passed to float-based APIs (math, numpy, json); mixing decimal strictness with float-land helpers.
Related errors
- Cannot hash a signaling NaN value.
- cannot convert NaN to integer ratio
- Cannot convert NaN to integer
- cannot round a NaN
- argument must be a multiple of 32, with a maximum of {IEEE_C
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/2ab03953714e4de6.
Report an issue: GitHub.