Given the table schema defined below (create-table.json
) I am getting the following error after I call put-item
using add-event1.json
followed by add-event2.json
:
A client error (ConditionalCheckFailedException) occurred when calling the PutItem operation: The conditional request failed
Why doesn't the ConditionExpression allow me to write both records? (I expect to have 2 records after the second operation)
I suspected that it was because of the non-key conditions used, but I don't see anything in the docs that indicates a lack of support for non-key conditions.
Create Table
$ aws dynamodb create-table --cli-input-json file://create-table.json
create-table.json
{
"TableName": "EVENTS_TEST",
"KeySchema": [
{ "AttributeName": "aggregateId", "KeyType": "HASH" },
{ "AttributeName": "streamRevision", "KeyType": "RANGE" }
],
"AttributeDefinitions": [
{ "AttributeName": "aggregateId", "AttributeType": "S" },
{ "AttributeName": "streamRevision", "AttributeType": "N" }
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10
}
}
Add First Record
$ aws dynamodb put-item --cli-input-json file://add-event1.json
add-event1.json
{
"TableName": "EVENTS_TEST",
"Item": {
"aggregateId": { "S": "id" },
"id": { "S": "119" },
"context": { "S": "*" },
"aggregate": { "S": "*" },
"streamRevision": { "N": "0" },
"commitId": { "S": "1119" },
"commitSequence": { "N": "0" },
"commitStamp": { "N": "1470185631511" },
"dispatched": { "BOOL": false },
"payload": { "S": "{ \"event\": \"bla\" }" }
},
"ExpressionAttributeNames": { "#name": "aggregate" },
"ConditionExpression": "attribute_not_exists(aggregateId) and attribute_not_exists(streamRevision) and #name <> :name and context <> :ctx",
"ExpressionAttributeValues": {
":name": { "S": "*" },
":ctx": { "S": "*" }
}
}
Add Second Record
$ aws dynamodb put-item --cli-input-json file://add-event2.json
add-event2.json
{
"TableName": "EVENTS_TEST",
"Item": {
"aggregateId": { "S": "id" },
"id": { "S": "123" },
"context": { "S": "myCtx" },
"aggregate": { "S": "myAgg" },
"streamRevision": { "N": "0" },
"commitId": { "S": "1123" },
"commitSequence": { "N": "0" },
"commitStamp": { "N": "1470185631551" },
"dispatched": { "BOOL": false },
"payload": { "S": "{ \"event\": \"bla2\" }" }
},
"ExpressionAttributeNames": { "#name": "aggregate" },
"ConditionExpression": "aggregateId <> :id and streamRevision <> :rev and #name <> :name and context <> :ctx",
"ExpressionAttributeValues": {
":id": { "S": "id" },
":rev": { "N": "0" },
":name": { "S": "myAgg" },
":ctx": { "S": "myCtx" }
}
}
Your goal is to save both records. There are 2 issues here
The combination of hash and range key make a record unique. Event 1 and event 2 have the same values for hash and range key. Therefore the second put-item wil simply overwrite the first record.
The ConditionExpression is evaluated just before putting a record. Your expression fails because when your event 2 is about to be inserted, DynamoDB discovers that a record with aggregateId “id1” already exists. The condition fails on "attribute_not_exists(aggregateId)", and you receive the ConditionalCheckFailedException This expression prevents overwriting of record 1 by record 2.
If you want to save both records you will have to come up with another choice of hash key and/or range key that better represents the unicity of your data item. You can not solve that with a ConditionExpression.
I received similar error.
The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: SMNKMSKJNSHBSGHVGHSB)
In my case I had not added sort key in my table and my second item had the same primary key as of first item. It worked after I added sort key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With