boto/boto3 · error · TypeError

Float types are not supported. Use Decimal types instead.

Error message

Float types are not supported. Use Decimal types instead.

What it means

Raised by TypeSerializer._is_number when the value is a float. DynamoDB numbers have arbitrary precision (up to 38 digits) which Python float cannot represent exactly, so boto3 rejects floats outright and requires the decimal.Decimal type. This fires before the generic 'Unsupported type' error because _is_number checks isinstance(value, float) explicitly.

Source

Thrown at boto3/dynamodb/types.py:171

            raise TypeError(msg)

        return dynamodb_type

    def _is_null(self, value):
        if value is None:
            return True
        return False

    def _is_boolean(self, value):
        if isinstance(value, bool):
            return True
        return False

    def _is_number(self, value):
        if isinstance(value, (int, Decimal)):
            return True
        elif isinstance(value, float):
            raise TypeError(
                'Float types are not supported. Use Decimal types instead.'
            )
        return False

    def _is_string(self, value):
        if isinstance(value, str):
            return True
        return False

    def _is_binary(self, value):
        if isinstance(value, (Binary, bytearray, bytes)):
            return True
        return False

    def _is_set(self, value):
        if isinstance(value, collections_abc.Set):
            return True
        return False

View on GitHub (pinned to c7b4afac23)

Solutions

  1. Use Decimal(str(float_value)) to convert: Decimal(str(9.99)).
  2. Parse JSON with parse_float=Decimal: json.loads(data, parse_float=Decimal).
  3. Use Decimal literals directly: Decimal('9.99').

Example fix

# before
table.put_item(Item={'price': 9.99})

# after
from decimal import Decimal
table.put_item(Item={'price': Decimal('9.99')})
# or when loading from JSON
import json
from decimal import Decimal
data = json.loads(raw, parse_float=Decimal)
Defensive patterns

Strategy: validation

Validate before calling

from decimal import Decimal

def to_dynamodb_number(value):
    if isinstance(value, float):
        return Decimal(str(value))
    return value

def normalize_item(item):
    return {k: to_dynamodb_number(v) if isinstance(v, (int, float)) else v for k, v in item.items()}

# For JSON parsing:
# json.loads(raw_text, parse_float=Decimal)

Type guard

from decimal import Decimal

def is_dynamodb_number(v) -> bool:
    return isinstance(v, (int, Decimal)) and not isinstance(v, bool)

Prevention

When it happens

Trigger: table.put_item(Item={'price': 9.99}) — 9.99 is a float. Also serialize(3.14), or a set containing floats like {1.0, 2.0} (fails _is_type_set for number because _is_number raises on each float).

Common situations: Loading JSON with json.load (which produces floats for decimal numbers) and passing directly to DynamoDB; computing averages or currency as floats; migrating from an ORM that emits floats.

Related errors


AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04). Data as JSON: /data/errors/a235c6851b5442ae.json. Report an issue: GitHub.