Boto 3 DynamoDB batchWriteItem Invalid attribute value type when specifying types

Question:

I have a strange problem with Python Boto3 when trying to do a batch_write_item to a DynamoDB table. I am following the documentation and trying to write a singe item. The table is setup correctly and I can run batch-write-item via the AWS cli no problem.

Assuming the client and DynamoDB are set up correctly I run:

client.batch_write_item(RequestItems={
    "myTable": [
        {
            "PutRequest": {
                "Item": {
                    "name": {
                        "S": "hello"
                    },
                    "value": {
                        "S": "world"
                    }
                }
            }
        }
    ]
})

I get the following error:

botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the BatchWriteItem operation: Invalid attribute value type

If I change it, removing the types and run:

client.batch_write_item(RequestItems={
    "myTable": [
        {
            "PutRequest": {
                "Item": {
                    "name": "hello",
                    "value": "world"
                }
            }
        }
    ]
})

It works as expected.

I need to use the previous format which follows the documentation and is compatibale with AWS cli.

Is the documentation wrong or I missed a configuration setting, version issue or something else?

Asked By: Jeff S.

||

Answers:

This just got me as well, looks like you’re using a DynamoDB resource, not a client. They both provide the same function but it acts very slightly differently. Here’s what you’re looking for:

http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html#DynamoDB.ServiceResource.batch_write_item

That aside, the docs are still pretty unclear. Here’s what I found:

  • When using a resource (what you’re currently doing), you may specify the type of non-key attributes, and you must not specify the type of key attributes
  • When using a client (the other option), you must specify the type of all attributes.

Using the DynamoDB resource:

resource = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')

mytable = resource.create_table(
    TableName='mytable',
    KeySchema=[{ 'AttributeName': 'name', 'KeyType': 'HASH' }],
    AttributeDefinitions=[{ 'AttributeName': 'name', 'AttributeType': 'S' }],
    ProvisionedThroughput={ 'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5 }
)

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': { 'S': 'myname' },
            'value': { 'S': 'myvalue' }
        }}}]
    })
    print(f'resource, specify all types : write succeeded.')
except Exception as e:
    print(f'resource, specify all types : write failed: {e}')

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': 'myname',
            'value': { 'S': 'myvalue' }
        }}}]
    })
    print(f'resource, specify value only: write succeeded.')
except Exception as e:
    print(f'resource, specify value only: write failed: {e}')

try:
    resource.batch_write_item(RequestItems={
        'mytable': [{ 'PutRequest': { 'Item': {
            'name': 'myname',
            'value': 'myvalue'
        }}}]
    })
    print(f'resource, specify none      : write succeeded.')
except Exception as e:
    print(f'resource, specify none      : write failed: {e}')

Output

resource, specify all types : write failed:
    An error occurred (ValidationException) when calling the BatchWriteItem operation: Invalid attribute value type
resource, specify value only: write succeeded.
resource, specify none      : write succeeded.

And then using the DynamoDB client (replace all “resource”s above with client)

client = boto3.client('dynamodb', endpoint_url='http://localhost:8000')
try:
    client.batch_write_item(RequestItems={    
....

Output

client, specify all types : write succeeded.
client, specify value only: write failed: Parameter validation failed:
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.name, value: myname, type: <class 'str'>, valid types: <class 'dict'>
client, specify none      : write failed: Parameter validation failed:
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.name, value: myname, type: <class 'str'>, valid types: <class 'dict'>
    Invalid type for parameter RequestItems.mytable[0].PutRequest.Item.value, value: myvalue, type: <class 'str'>, valid types: <class 'dict'>
Answered By: Thomas Steinke

I was getting the same error message, but it ended up being a different issue. In my case, I was sending a BatchWriteItem request, but had a request that looked like this:

"PutRequest": {
    "Item": {
        "Id": "5cc230c65d0948c0bcb5910cc9312e6a",
        "Platform": "slack",
        "SlackMessageId": None,
        "SlackUserId": "U016H83F39V",
        "SlackTeamId": "UTKUSRRSL&0",
        "SlackOrgId": "TTKUSRQM6",
        "Timestamp": Decimal("1618593370.910027027130126953125"),
        "Selection": "yellow",
        "Elaboration": "",
        "Emotion": None,
        "MeetingHours": None,
        "PrivateElaboration": None,
        "Reactions": None,
    }
}

The issue is that according to the API documentation:

Attribute values must not be null; string and binary type attributes must have lengths greater than zero; and set type attributes must not be empty. Requests that contain empty values are rejected with a ValidationException exception.

The issue is the None values, replacing them with non empty strings (i.e. 'null') solves the issue and lets the request go through! Hope this helps someone out.

Answered By: Allen N
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.