RustPython/RustPython · error · TypeError

Cannot convert %r to Decimal

Error message

Cannot convert %r to Decimal

What it means

Decimal(value) accepts str, int, a 3-element list/tuple, float (under the FloatOperation signal), and Decimal; this TypeError is the fallback when value is none of those. Typical offenders are complex, None, bytes, and Fraction, which look numeric but have no defined exact conversion in the constructor.

Source

Thrown at Lib/_pydecimal.py:608

                    raise ValueError("The third value in the tuple must "
                                     "be an integer, or one of the "
                                     "strings 'F', 'n', 'N'.")
            return self

        if isinstance(value, float):
            if context is None:
                context = getcontext()
            context._raise_error(FloatOperation,
                "strict semantics for mixing floats and Decimals are "
                "enabled")
            value = Decimal.from_float(value)
            self._exp  = value._exp
            self._sign = value._sign
            self._int  = value._int
            self._is_special  = value._is_special
            return self

        raise TypeError("Cannot convert %r to Decimal" % value)

    @classmethod
    def from_number(cls, number):
        """Converts a real number to a decimal number, exactly.

        >>> Decimal.from_number(314)              # int
        Decimal('314')
        >>> Decimal.from_number(0.1)              # float
        Decimal('0.1000000000000000055511151231257827021181583404541015625')
        >>> Decimal.from_number(Decimal('3.14'))  # another decimal instance
        Decimal('3.14')
        """
        if isinstance(number, (int, Decimal, float)):
            return cls(number)
        raise TypeError("Cannot convert %r to Decimal" % number)

    @classmethod
    def from_float(cls, f):

View on GitHub (pinned to aaeab4f754)

Solutions

  1. For Fraction use Decimal(f.numerator) / Decimal(f.denominator) (exact to context precision) or Decimal(str(f)).
  2. Decode bytes before use: Decimal(b'1.5'.decode()).
  3. Guard with isinstance(value, (str, int, float, Decimal, tuple, list)) and give None an explicit default like Decimal(0).

Example fix

# before
from fractions import Fraction
d = Decimal(Fraction(1, 3))  # TypeError

# after
f = Fraction(1, 3)
d = Decimal(f.numerator) / Decimal(f.denominator)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(value, (str, int, float, Decimal, list, tuple)):
    raise TypeError(f'cannot build Decimal from {type(value).__name__}')

Type guard

def can_convert_to_decimal(v):
    return isinstance(v, (str, int, float, Decimal, list, tuple))

Try / catch

try:
    d = Decimal(value)
except TypeError:
    d = None  # or convert explicitly, e.g. via str(value)

Prevention

When it happens

Trigger: Decimal(Fraction(1, 3)); Decimal(None) from an unset config value; Decimal(complex(1, 2)); Decimal(b'1.5') with a bytes payload.

Common situations: Passing a Fraction expecting exact conversion; a defaulted-None variable reaching the constructor; unparsed bytes input from a socket or file.

Related errors


AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17). Data as JSON: /api/errors/a4e1cb88749f6bf3. Report an issue: GitHub.