Search code examples
amazon-web-servicesrestaws-lambdaamazon-dynamodbaws-api-gateway

AWS Lambda function: TypeError: PutCommand is not a constructor


The test even JSON that triggered the error:

{
  "body": "{\"email\": \"test@example.com\"}"
}

The error:

Response
{
  "errorType": "TypeError",
  "errorMessage": "PutCommand is not a constructor",
  "trace": [
    "TypeError: PutCommand is not a constructor",
    "    at exports.handler (/var/task/index.js:16:19)",
    "    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1147:29)"
  ]
}

The directory structure: handleWaitingList node_modules [various other directories, including @aws-sdk] index.js

Contents of index.js:

const { DynamoDBClient, PutCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({ region: "us-east-2" });

exports.handler = async (event) => {
  const requestBody = JSON.parse(event.body);
  const email = requestBody.email;

  const params = {
    TableName: "WaitingList",
    Item: {
      email: { S: email }
    }
  };

  const command = new PutCommand(params);

  try {
    await client.send(command);
    return {
      statusCode: 200,
      body: JSON.stringify("Successfully added to the waiting list"),
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(`An error occurred: ${error}`),
    };
  }
};

How I have set up the .zip file I uploaded: In the terminal, I created index.js then ran this in the same directory: npm init -y npm install @aws-sdk/client-dynamodb zip -r lambda-package.zip index.js node_modules/

Various other information:

  • CORS is wide open
  • Runtime is Node.js 18.x
  • Handler is index.handler
  • In CloudWatch logs, I see: "@log [number]:/aws/lambda/handleWaitingList" as well as the same error from the test.
  • On localhost upon submit, it says: "An error occurred while adding to the waiting list."
  • I set up API Gateway and DynamoDB

What I have tried:

  • Trying to use import/require statements without uploading a zip
  • Switching import to require statements and vice versa
  • Swtiching from .js to .mjs
  • Re-installing aws-sdk various ways (e.g., other npm installs)
  • Checking the file encoding of index.js
  • Creating a layer, which I have never done before, so it may have been wrong

I am trying to set up a waiting list where users can enter an email and it is added to a database. I am using React to do this. My plan is to Create a DynamoDB table to hold the waiting list emails, create a Lambda function to interact with the DynamoDB table, create an API Gateway to expose the Lambda function as a REST API, and use my react .js to send data to the API. This is all going fine except for the Lambda function part, as my Lambda function is not passing tests.


Solution

  • @jarmod's comment led to the fix. The actual command for putting an item in DynamoDB with the AWS SDK for JavaScript v3 is PutItemCommand.

    PutCommand is not a constructor means that the class or function I was trying to instantiate doesn't exist in the SDK version you're using. The confusion was generated from online documentation from PutCommand and lack of knowledge about PutItemCommand.

    Replacing PutCommand with PutItemCommand solves the problem.