Search code examples
typescriptamazon-dynamodbaws-sdk-jsaws-sdk-nodejs

AWS NodeJS TypeScript SDK V3 DynamoDB PutItemCommand - TypeError: Cannot read properties of undefined (reading '0')


I am building an application that manages information about different media such as videos, images, etc. The app uses a DynamoDB for storing the information and I use the TypeScript AWS SDK to connect to the database.

I am currently coding the part for storing information related to videos but I am having trouble when trying to insert an object in the DynamoDB table and I am using this code to do it:

import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';

export async function postVideo(
    event: APIGatewayProxyEvent,
    ddbClient: DynamoDBClient
): Promise<APIGatewayProxyResult> {
    const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);

    const item = JSON.parse(event.body!);

    const currentDateTime = new Date().toISOString();
    const pk = `VIDEO`;
    const sk = `${item.owner}#${item.title}#${currentDateTime}`;
    item.PK = pk;
    item.SK = sk;

    const result = await ddbDocClient.send(
        new PutItemCommand({
            TableName: process.env.TABLE_NAME,
            Item: item,
        })
    );
    console.log(result);

    return {
        statusCode: 201,
        body: JSON.stringify({ PK: pk, SK: sk }),
    };
}

I know that when using the DynamoDBClient I need to specify the type of each of the fields of the item, so I decided to use the DynamoDBDocumentClient instead of directly using the DynamoDBClient in order to not have to marshall-unmarshall, but when I try to insert the item in the database, it throws a TypeError: Cannot read properties of undefined (reading '0').

When trying to insert the item, it contains something like this:

{
  owner: "Test",
  title: "Test",
  description: "Test",
  link: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  PK: "VIDEO",
  SK: "Test#Test#2023-06-20T17:20:59.683Z",
}

I don't know if I am missing something here. My guess is that it isn't getting the types of the item correctly but I thought it was supossed to get them directly from the JS object.


Solution

  • Because you're using the DynamoDBDocumentClient you need to use PutCommand from "@aws-sdk/lib-dynamodb", instead of PutItemCommand from @aws-sdk/client-dynamodb.

    Use this import instead:

    import { PutCommand } from "@aws-sdk/lib-dynamodb";
    

    This is slop on Amazon's part, IMO. There should only be one set of commands, but I guess it makes sense.