Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DynamoDB put-item ConditionalCheckFailedException

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" }
  }
}
like image 941
Mark J Miller Avatar asked Aug 03 '16 02:08

Mark J Miller


2 Answers

Your goal is to save both records. There are 2 issues here

  1. With your choice of hash and range key it is impossible to save both records

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.

  1. Your ConditionExpression prevents the replacement of record 1 by record 2

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.

like image 139
Peter Fennema Avatar answered Oct 28 '22 17:10

Peter Fennema


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.

like image 32
Suresh Kumar Avatar answered Oct 28 '22 15:10

Suresh Kumar