Skip to content

DynamoDB: Incorrect item size calculation for Number attributes #10176

Description

@hannes-ucsc

(Posted by Claude Code)

Description

Moto's DynamoDB DynamoType.size() method computes the size of a Number attribute as len(str(value)) — the length of the decimal string representation. Real DynamoDB uses a more compact encoding where the size is approximately ceil(significant_digits / 2) + 1 bytes, as documented by AWS.

For example, a Unix timestamp like 1786461547 (10 digits):

  • Moto computes: len("1786461547") = 10 bytes
  • Real DynamoDB uses: ceil(10 / 2) + 1 = 6 bytes

This means moto's 400 KB item size check is more restrictive than real DynamoDB's. Items that DynamoDB accepts can be rejected by moto with ValidationException: Item size has exceeded the maximum allowed size.

Steps to reproduce

import boto3
from moto import mock_aws

@mock_aws
def test():
    client = boto3.client("dynamodb", region_name="us-east-1")
    client.create_table(
        TableName="test",
        KeySchema=[{"AttributeName": "pk", "KeyType": "HASH"}],
        AttributeDefinitions=[{"AttributeName": "pk", "AttributeType": "S"}],
        BillingMode="PAY_PER_REQUEST",
    )

    # This is accepted by real DynamoDB but rejected by moto
    client.put_item(
        TableName="test",
        Item={
            "pk": {"S": "x" * 40},
            "data": {"B": b"x" * 409530},
            "ttl": {"N": "1786461547"},
        },
    )

test()

Root cause

In moto/dynamodb/models/dynamo_type.py, DynamoType.size():

def size(self) -> int:
    if self.is_number():
        value_size = len(str(self.value))  # <-- should be ceil(digits / 2) + 1

Expected behavior

Number attribute size should be computed as ceil(significant_digits / 2) + 1 to match DynamoDB's actual encoding, per the AWS documentation on item size calculations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions