Dynamodb2 Table.get_item() throws ValidationException "The number of conditions on the keys is invalid"
Question: I am just doing a simple task in DynamoDB:

  1. Create a Table, 
  2. Add an Item to it
  3. Query the Table for that Item. 

Here's a script that I am using:

    
    
    from boto.dynamodb2.fields import HashKey, RangeKey, AllIndex, GlobalAllIndex
    from boto.dynamodb2.items import Item
    from boto.dynamodb2.layer1 import DynamoDBConnection
    from boto.dynamodb2.table import Table
    
    # Using DynamoDB Local
    conn = DynamoDBConnection(host='localhost', port=8000, is_secure=False)
    
    ## ----- Create a table -----
    throughput = {
        'write': 1,
        'read': 1
    }
    
    schema = [
        HashKey('id'),
        RangeKey('rating')
    ]
    
    local_indexes = [
        AllIndex('local_all_index_seats', parts=[
            HashKey('id'),
            RangeKey('seats')
        ])
    ]
    
    global_indexes = [
        GlobalAllIndex('global_all_index_color', parts=[
            HashKey('color'),
            RangeKey('rating')
        ])
    ]
    
    new_table = Table.create('items', schema=schema, indexes=local_indexes,
                             global_indexes=global_indexes, connection=conn,
                             throughput=throughput)
    print 'Table created'
    ## -------- Table created ---------
    
    ## -------- Add an item --------
    
    items_table = Table('items', connection=conn)  # New reference to the table we created
    
    new_item_data = {
        "category": "Sofa",
        "rating": "4",
        "color": "beige",
        "seats": "6",
        "id": "first_id"
    }
    
    new_item = Item(items_table, new_item_data)
    new_item.save()
    print 'New item saved'
    ## -------- Item added --------
    
    ## -------- Query Item --------
    
    items_table = Table('items', connection=conn)  # New reference to the table we created
    queried_item = items_table.get_item(id='first_id')
    print 'Query done. Category is: {}'.format(queried_item['Category'])
    
    ## -------- Querying Done --------
    

When I run this script, I get a `ValidationException`:

    
    
    (backend)aniket [~/PycharmProjects/website_backend] -> python reproduce.py                                                                                 ±[●●][master]
    Table created
    New item saved
    Traceback (most recent call last):
      File "reproduce.py", line 59, in <module>
        queried_item = items_table.get_item(id='first_id')
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/table.py", line 705, in get_item
        consistent_read=consistent
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 1099, in get_item
        body=json.dumps(params))
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2842, in make_request
        retry_handler=self._retry_handler)
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/connection.py", line 954, in _mexe
        status = retry_handler(response, i, next_sleep)
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2882, in _retry_handler
        response.status, response.reason, data)
    boto.dynamodb2.exceptions.ValidationException: ValidationException: 400 Bad Request
    {u'Message': u'The number of conditions on the keys is invalid', u'__type': u'com.amazon.coral.validate#ValidationException'}
    

I am pretty sure I am doing something wrong, but I can't figure out what. The
DynamoDB Docs mention that it is possible to query using _only_ the HashKey,
so what I am doing seems to be pretty normal.

In case it helps, I also added debug logging, and here's the output:

    
    
    (backend)aniket [~/PycharmProjects/website_backend] -> python reproduce.py                                                                                 ±[●●][master]
    2015-04-15 20:04:48,218 [DEBUG] (boto) Using access key found in shared credential file.
    2015-04-15 20:04:48,218 [DEBUG] (boto) Using secret key found in shared credential file.
    2015-04-15 20:04:48,219 [DEBUG] (boto) Method: POST
    2015-04-15 20:04:48,219 [DEBUG] (boto) Path: /
    2015-04-15 20:04:48,219 [DEBUG] (boto) Data: {"GlobalSecondaryIndexes": [{"KeySchema": [{"KeyType": "HASH", "AttributeName": "color"}, {"KeyType": "RANGE", "AttributeName": "rating"}], "IndexName": "global_all_index_color", "Projection": {"ProjectionType": "ALL"}, "ProvisionedThroughput": {"WriteCapacityUnits": 5, "ReadCapacityUnits": 5}}], "AttributeDefinitions": [{"AttributeName": "id", "AttributeType": "S"}, {"AttributeName": "rating", "AttributeType": "S"}, {"AttributeName": "seats", "AttributeType": "S"}, {"AttributeName": "color", "AttributeType": "S"}], "LocalSecondaryIndexes": [{"KeySchema": [{"KeyType": "HASH", "AttributeName": "id"}, {"KeyType": "RANGE", "AttributeName": "seats"}], "IndexName": "local_all_index_seats", "Projection": {"ProjectionType": "ALL"}}], "ProvisionedThroughput": {"WriteCapacityUnits": 1, "ReadCapacityUnits": 1}, "TableName": "items", "KeySchema": [{"KeyType": "HASH", "AttributeName": "id"}, {"KeyType": "RANGE", "AttributeName": "rating"}]}
    2015-04-15 20:04:48,219 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '942', 'X-Amz-Target': 'DynamoDB_20120810.CreateTable'}
    2015-04-15 20:04:48,219 [DEBUG] (boto) Host: localhost
    2015-04-15 20:04:48,219 [DEBUG] (boto) Port: 8000
    2015-04-15 20:04:48,219 [DEBUG] (boto) Params: {}
    2015-04-15 20:04:48,219 [DEBUG] (boto) establishing HTTP connection: kwargs={'port': 8000, 'timeout': 70}
    2015-04-15 20:04:48,219 [DEBUG] (boto) Token: None
    2015-04-15 20:04:48,219 [DEBUG] (boto) CanonicalRequest:
    POST
    /
    
    host:localhost
    x-amz-date:20150415T143448Z
    x-amz-target:DynamoDB_20120810.CreateTable
    
    host;x-amz-date;x-amz-target
    4d4b471da224cff0353d444ba9f31ecbda7ac332b618c8db038940477cf5fbd9
    2015-04-15 20:04:48,219 [DEBUG] (boto) StringToSign:
    AWS4-HMAC-SHA256
    20150415T143448Z
    20150415/localhost/localhost/aws4_request
    a54fd62c95217cf6fafe69876388ac3ae8ffd4b2d87e23f71a131741d3e64792
    2015-04-15 20:04:48,219 [DEBUG] (boto) Signature:
    51e3035fcfef8b31f8d6c0e22779ba4b17990d3f91f8dfda6b70e559ee5c384e
    2015-04-15 20:04:48,220 [DEBUG] (boto) Final headers: {'Content-Length': '942', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143448Z', 'X-Amz-Target': 'DynamoDB_20120810.CreateTable', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=host;x-amz-date;x-amz-target,Signature=51e3035fcfef8b31f8d6c0e22779ba4b17990d3f91f8dfda6b70e559ee5c384e'}
    2015-04-15 20:04:49,004 [DEBUG] (boto) Response headers: [('x-amzn-requestid', 'e4cd23ec-ad5a-4f94-8d80-dd9f002b0f28'), ('content-length', '1160'), ('content-type', 'application/x-amz-json-1.0'), ('x-amz-crc32', '175075191'), ('server', 'Jetty(8.1.12.v20130726)')]
    2015-04-15 20:04:49,004 [DEBUG] (boto) Saw HTTP status: 200
    2015-04-15 20:04:49,004 [DEBUG] (boto) Validating crc32 checksum for body: {"TableDescription":{"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"rating","AttributeType":"S"},{"AttributeName":"seats","AttributeType":"S"},{"AttributeName":"color","AttributeType":"S"}],"TableName":"items","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"TableStatus":"ACTIVE","CreationDateTime":1429108488.651,"ProvisionedThroughput":{"LastIncreaseDateTime":0.000,"LastDecreaseDateTime":0.000,"NumberOfDecreasesToday":0,"ReadCapacityUnits":1,"WriteCapacityUnits":1},"TableSizeBytes":0,"ItemCount":0,"LocalSecondaryIndexes":[{"IndexName":"local_all_index_seats","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"seats","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexSizeBytes":0,"ItemCount":0}],"GlobalSecondaryIndexes":[{"IndexName":"global_all_index_color","KeySchema":[{"AttributeName":"color","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexStatus":"ACTIVE","ProvisionedThroughput":{"ReadCapacityUnits":5,"WriteCapacityUnits":5},"IndexSizeBytes":0,"ItemCount":0}]}}
    2015-04-15 20:04:49,004 [DEBUG] (boto) {"TableDescription":{"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"rating","AttributeType":"S"},{"AttributeName":"seats","AttributeType":"S"},{"AttributeName":"color","AttributeType":"S"}],"TableName":"items","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"TableStatus":"ACTIVE","CreationDateTime":1429108488.651,"ProvisionedThroughput":{"LastIncreaseDateTime":0.000,"LastDecreaseDateTime":0.000,"NumberOfDecreasesToday":0,"ReadCapacityUnits":1,"WriteCapacityUnits":1},"TableSizeBytes":0,"ItemCount":0,"LocalSecondaryIndexes":[{"IndexName":"local_all_index_seats","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"seats","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexSizeBytes":0,"ItemCount":0}],"GlobalSecondaryIndexes":[{"IndexName":"global_all_index_color","KeySchema":[{"AttributeName":"color","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexStatus":"ACTIVE","ProvisionedThroughput":{"ReadCapacityUnits":5,"WriteCapacityUnits":5},"IndexSizeBytes":0,"ItemCount":0}]}}
    Table created
    2015-04-15 20:04:49,004 [DEBUG] (boto) Method: POST
    2015-04-15 20:04:49,004 [DEBUG] (boto) Path: /
    2015-04-15 20:04:49,004 [DEBUG] (boto) Data: {"Expected": {"category": {"Exists": false}, "rating": {"Exists": false}, "id": {"Exists": false}, "color": {"Exists": false}, "seats": {"Exists": false}}, "Item": {"category": {"S": "Sofa"}, "rating": {"S": "4"}, "id": {"S": "first_id"}, "color": {"S": "beige"}, "seats": {"S": "6"}}, "TableName": "items"}
    2015-04-15 20:04:49,004 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '307', 'X-Amz-Target': 'DynamoDB_20120810.PutItem'}
    2015-04-15 20:04:49,005 [DEBUG] (boto) Host: localhost
    2015-04-15 20:04:49,005 [DEBUG] (boto) Port: 8000
    2015-04-15 20:04:49,005 [DEBUG] (boto) Params: {}
    2015-04-15 20:04:49,005 [DEBUG] (boto) Token: None
    2015-04-15 20:04:49,005 [DEBUG] (boto) CanonicalRequest:
    POST
    /
    
    host:localhost
    x-amz-date:20150415T143449Z
    x-amz-target:DynamoDB_20120810.PutItem
    
    host;x-amz-date;x-amz-target
    96fd2aee6eabd2c812d7111c9a47ba21c31ccc86859c963cfa3fd69a18edc957
    2015-04-15 20:04:49,005 [DEBUG] (boto) StringToSign:
    AWS4-HMAC-SHA256
    20150415T143449Z
    20150415/localhost/localhost/aws4_request
    9ed70485aa9e7036fd2db89e34036c9e24a3c91b6e35dbb7fc2cd476b4766f21
    2015-04-15 20:04:49,005 [DEBUG] (boto) Signature:
    1d81bae229584b7466c6951a71010c8e2d7a441e80b2e9b5a60d9782859345dc
    2015-04-15 20:04:49,005 [DEBUG] (boto) Final headers: {'Content-Length': '307', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143449Z', 'X-Amz-Target': 'DynamoDB_20120810.PutItem', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=host;x-amz-date;x-amz-target,Signature=1d81bae229584b7466c6951a71010c8e2d7a441e80b2e9b5a60d9782859345dc'}
    2015-04-15 20:04:49,287 [DEBUG] (boto) Response headers: [('x-amzn-requestid', '80571386-1ce7-4f9b-84fb-6805a0dfa171'), ('content-length', '2'), ('content-type', 'application/x-amz-json-1.0'), ('x-amz-crc32', '2745614147'), ('server', 'Jetty(8.1.12.v20130726)')]
    2015-04-15 20:04:49,287 [DEBUG] (boto) Saw HTTP status: 200
    2015-04-15 20:04:49,287 [DEBUG] (boto) Validating crc32 checksum for body: {}
    2015-04-15 20:04:49,287 [DEBUG] (boto) {}
    New item saved
    2015-04-15 20:04:49,288 [DEBUG] (boto) Method: POST
    2015-04-15 20:04:49,288 [DEBUG] (boto) Path: /
    2015-04-15 20:04:49,288 [DEBUG] (boto) Data: {"ConsistentRead": false, "TableName": "items", "Key": {"id": {"S": "first_id"}}}
    2015-04-15 20:04:49,288 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '81', 'X-Amz-Target': 'DynamoDB_20120810.GetItem'}
    2015-04-15 20:04:49,289 [DEBUG] (boto) Host: localhost
    2015-04-15 20:04:49,289 [DEBUG] (boto) Port: 8000
    2015-04-15 20:04:49,289 [DEBUG] (boto) Params: {}
    2015-04-15 20:04:49,289 [DEBUG] (boto) Token: None
    2015-04-15 20:04:49,289 [DEBUG] (boto) CanonicalRequest:
    POST
    /
    
    host:localhost
    x-amz-date:20150415T143449Z
    x-amz-target:DynamoDB_20120810.GetItem
    
    host;x-amz-date;x-amz-target
    1563f0044c8fc746bb9a0ec2e4754e5fd03e62d604102f0745920d8c49481e88
    2015-04-15 20:04:49,289 [DEBUG] (boto) StringToSign:
    AWS4-HMAC-SHA256
    20150415T143449Z
    20150415/localhost/localhost/aws4_request
    059601773b2e09d4c42f984cb185bf565e47a9dff8d42b3ae15dd61b4fc41f76
    2015-04-15 20:04:49,289 [DEBUG] (boto) Signature:
    e22cfe8b3e3e03dfa4e05ec11f333f9aaff0edcdbf498ebfa9d0e7dc5b452916
    2015-04-15 20:04:49,290 [DEBUG] (boto) Final headers: {'Content-Length': '81', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143449Z', 'X-Amz-Target': 'DynamoDB_20120810.GetItem', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=host;x-amz-date;x-amz-target,Signature=e22cfe8b3e3e03dfa4e05ec11f333f9aaff0edcdbf498ebfa9d0e7dc5b452916'}
    2015-04-15 20:04:49,315 [DEBUG] (boto) Response headers: [('x-amzn-requestid', '51547354-f266-4870-8c79-6192e7d7c7b5'), ('content-length', '118'), ('content-type', 'application/x-amz-json-1.0'), ('server', 'Jetty(8.1.12.v20130726)')]
    2015-04-15 20:04:49,316 [DEBUG] (boto) Saw HTTP status: 400
    2015-04-15 20:04:49,316 [DEBUG] (boto) {"__type":"com.amazon.coral.validate#ValidationException","Message":"The number of conditions on the keys is invalid"}
    Traceback (most recent call last):
      File "reproduce.py", line 71, in <module>
        queried_item = items_table.get_item(id='first_id')
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/table.py", line 705, in get_item
        consistent_read=consistent
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 1099, in get_item
        body=json.dumps(params))
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2842, in make_request
        retry_handler=self._retry_handler)
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/connection.py", line 954, in _mexe
        status = retry_handler(response, i, next_sleep)
      File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2882, in _retry_handler
        response.status, response.reason, data)
    boto.dynamodb2.exceptions.ValidationException: ValidationException: 400 Bad Request
    {u'Message': u'The number of conditions on the keys is invalid', u'__type': u'com.amazon.coral.validate#ValidationException'}
    


Answer: `GetItem` in DynamoDB needs the same number of key conditions as the number of
keys, largely because the operation must find the exact item in the table. For
the primary key, you must provide all of the attributes. There should be only
one item, if any, matching the **Get** expectations. This is written in the
[DynamoDB
doc](http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html).

On contrast, you can use `Query` to get multiple (possibly) items for a given
condition. Since you know this I believe, I think you mistakenly used the
wrong `get_item()` api, instead of `query()` or something alike.

