Search code examples
javascriptamazon-web-servicesamazon-dynamodbaws-sdk-nodejs

AWS NodeJS SDK V3 DynamoDB UpdateItem - TypeError: Cannot read property '0' of undefined


I am trying to get a basic database update operation to work in nodejs using the new AWS SDK V3 for NodeJS.

The data object that I am trying to update looks like this:

{
  auth: { BOOL: false },
  username: { S: 'siegbert' },
  secondsLeft: { N: 49985 },
  userid: { S: '123456' }
}

In the same file I have already succesfully done a GetItemCommand using the SDK V3.

Unfortunately I keep getting a really weird error when using the AWS SDK v3, when using the SDK v2, the exact same params seem to work. I tried looking into the docs but the update operation is not really well documented yet.

var params = {
    TableName: "tableXYZ",
    Key: {
        userid: user.userid.S,
    },
    UpdateExpression: "SET secondsLeft = :newsecondsLeft", 
    ExpressionAttributeValues: { 
        ":newsecondsLeft": user.secondsLeft.N,
    },
    ReturnValues: "UPDATED_NEW"
};


try {
        const data = await dbclient.send(new UpdateItemCommand(params));
        console.log("data:" + JSON.stringify(data));
        return true;
    } catch (error) {
        console.error(error);
        return false;
    }

This basically throws

TypeError: Cannot read property '0' of undefined
    at Object.AttributeValue.visit (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\models\models_0.js:1101:40)
    at XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:5074:20
    at Array.reduce (<anonymous>)
    at serializeAws_json1_0ExpressionAttributeValueMap (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:5068:34)
    at serializeAws_json1_0UpdateItemInput (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:6067:40)
    at Object.serializeAws_json1_0UpdateItemCommand (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:474:27)
    at serialize (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\commands\UpdateItemCommand.js:42:30)
    at XX\node_modules\@aws-sdk\middleware-serde\dist\cjs\serializerMiddleware.js:5:27
    at XX\node_modules\@aws-sdk\middleware-logger\dist\cjs\loggerMiddleware.js:6:28

When using the exact same params but with the SDK v2, it works:

var docClient = new AWS.DynamoDB.DocumentClient();

docClient.update(params, function (err, data) {
    if (err) {
        console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
    } else {
        console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
    }
});

Any help on how to use the SDK V3 for the update would be appreciated!


Solution

  • Couple of corrections:

    • when passing values we need to pass the object with type. so, instead of user.userid.S pass entire user.userid. Since its not able to determine the type, it is assuming as an array and trying to get the first element of the array and resulting in that error.
    • Numeric values, should simply be passed as String value of type 'N',like secondsLeft: { N: "49985" }

    Here is the updated code.

    const { DynamoDB, UpdateItemCommand } = require("@aws-sdk/client-dynamodb");
    const dbclient = new DynamoDB({ region: "us-east-1" });
    const user = {
      auth: { BOOL: false },
      username: { S: "siegbert" },
      secondsLeft: { N: "49985" },
      userid: { S: "123456" },
    };
    var params = {
      TableName: "tableXYZ",
      Key: {
        id: user.userid,
      },
      UpdateExpression: "SET secondsLeft = :newsecondsLeft",
      ExpressionAttributeValues: {
        ":newsecondsLeft": user.secondsLeft,
      },
      ReturnValues: "UPDATED_NEW",
    };
    
    dbclient
      .send(new UpdateItemCommand(params))
      .then((result) => {
        console.log("data:" + result);
      })
      .catch((err) => {
        console.log("err", err);
      });