AWS DynamoDB update item command gets ValidationException: The provided key element does not match the schema

0

Given the table with user_id (partition key) and created_at (sort key):

{
  "user_id": {
    "S": "..."
  },
  "created_at": {
    "N": "...."
  },
  "bot_answer": {
    "S": "..."
  },
  "question": {
    "S": "..."
  }
}

My lambda receives the insert event from dynamodb:

{
    "Records": [
        {
            ....
            "eventName": "INSERT",
            ....
            "dynamodb": {
                ....
                "Keys": {
                    "user_id": {
                        "S": "user123"
                    },
                    "created_at": {
                        "N": "1681218896790"
                    }
                },
                "NewImage": {
                    "question": {
                        "S": "What is the capital of USA?"
                    },
                    "user_id": {
                        "S": "user123"
                    },
                    "created_at": {
                        "N": "1681218896790"
                    },
                    "bot_answer": {
                        "S": ""
                    }
                },
                .....
                "StreamViewType": "NEW_AND_OLD_IMAGES"
            },
            ......
        }
    ]
}

I try to update an item with the command (from execution logs):

{
  TableName: 'chat_messages_tbl',
  Key: { 
   user_id: { S: 'user123' }, 
   created_at: { N: '1681218896790' } 
  },
  UpdateExpression: 'SET bot_answer = :bot_answer',
  ExpressionAttributeValues: { ':bot_answer': { S: 'Hello from bot!' } },
  ReturnValues: 'UPDATED_NEW'
}

But I get the ValidationException: The provided key element does not match the schema

// sample code from lambda (nodejs)

const dynamoDB = DynamoDBDocumentClient.from(dynamoDBClient)
const result = await dynamoDB.send(new UpdateCommand({
  TableName: 'chat_messages_tbl',
  Key: { 
   user_id: { S: 'user123' }, 
   created_at: { N: '1681218896790' } 
  },
  UpdateExpression: 'SET bot_answer = :bot_answer',
  ExpressionAttributeValues: { ':bot_answer': { S: 'Hello from bot!' } },
  ReturnValues: 'UPDATED_NEW'
}))

NOTE since the created_at is a number, I also tried to send it in the update command without single quotes:

created_at: { N: 1681218896790 }  // instead of { N : '1681218896790' } 

Thanks, F.

profile picture
Fabio
asked a month ago52 views
2 Answers
4

Here you are using the DocumentClient which accepts native JSON data:

const dynamoDB = DynamoDBDocumentClient.from(dynamoDBClient)

If you want to continue using DynamoDB JSON you can use the low level client which you have also created:

// remove this client creation
// const dynamoDB = DynamoDBDocumentClient.from(dynamoDBClient)

// change the client to use the low level client you have created: dynamoDBClient
const result = await dynamoDBClient.send(new UpdateCommand({
  TableName: 'chat_messages_tbl',
  Key: { 
   user_id: { S: 'user123' }, 
   created_at: { N: '1681218896790' } 
  },
  UpdateExpression: 'SET bot_answer = :bot_answer',
  ExpressionAttributeValues: { ':bot_answer': { S: 'Hello from bot!' } },
  ReturnValues: 'UPDATED_NEW'
}))

Or if you want to use native JSON do the following:

const dynamoDB = DynamoDBDocumentClient.from(dynamoDBClient)
const result = await dynamoDB.send(new UpdateCommand({
  TableName: 'chat_messages_tbl',
  Key: { 
   user_id: 'user123' , 
   created_at:  '1681218896790' 
  },
  UpdateExpression: 'SET bot_answer = :bot_answer',
  ExpressionAttributeValues: { ':bot_answer': 'Hello from bot!' },
  ReturnValues: 'UPDATED_NEW'
}))

If you want more information on the differences on clients, check out this blog post: https://aws.amazon.com/blogs/database/exploring-amazon-dynamodb-sdk-clients/

profile pictureAWS
EXPERT
answered a month ago
profile picture
EXPERT
reviewed a month ago
3
Accepted Answer

Looks like you must pass native JS types:

Key: { 
    user_id: 'user123',  // No need to wrap in { S: '...' }
    created_at: 1681218896790  //  No need to wrap in  { N: '...' }
  },

Also, there is a lib to convert json to dynamodb types and back:

import {unmarshall, marshall} from '@aws-sdk/util-dynamodb'
profile picture
Fabio
answered a month ago
profile picture
EXPERT
reviewed a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions