1

Working in the Lambda console, using Node v.18 runtime, and am getting really confused while trying to do some really simple beginner tasks. Specifically, I want to write a Lambda that will be called from API Gateway. This called Lambda will contain / call other lambdas.

Any / all advice is welcome.

Here's some code:

index.mjs:

   import AWS from 'aws-sdk';     // <== ERROR HERE
    
    export const handler = async (event) => {
        const lambda = new AWS.Lambda();
    
        try {
            const fetchFunction = // <== ARN for lambda here. We don't even get this far.
        // ... more code to do stuff follows

When I test the Lambda function, it returns an error. Here is the part of the error message that I can't sort out:

  "errorMessage": "Cannot find package 'aws-sdk' imported from /var/task/index.mjs\nDid you mean to import aws-sdk/lib/aws.js?",
  "trace": [
    "Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'aws-sdk' imported from /var/task/index.mjs",
    "Did you mean to import aws-sdk/lib/aws.js?",

I've already researched a solution, but the more information I find, the more overwhelming it becomes.

Can anyone suggest a simple work-around / solution? I'm guessing this is really simple but I'm just not seeing a path to a solution.

Thanks in advance, m

7
  • It seems like your question should be "how to import the AWS SDK in a Lambda function" not "how to call one Lambda from another" since you are stuck on the import statement and haven't even gotten into the rest of the code yet. Commented May 24, 2023 at 14:29
  • Fair enough. I've changed the question to reflect this. Commented May 24, 2023 at 14:33
  • It depends on what version of NodeJS you are using, which affects what version of the AWS SDK is being included. But you should try replacing the import with const AWS = require('aws-sdk'). Commented May 24, 2023 at 14:38
  • 1
    I'm using Node v.18.x Commented May 24, 2023 at 14:40
  • OK? did you try my suggestion? Commented May 24, 2023 at 14:42

2 Answers 2

6

You're importing the v2 SDK. The node 18 lambda runtime only supports the v3 SDK.

May 2023 Lambda runtimeshttps://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html

You'll need to update your imports.

import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';

You can see more of the syntax in the guide. https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/preview/client/lambda/command/InvokeCommand/

If you're looking for more examples to get you started, I would suggest the Code Library. It has a good collection of examples in V3.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I managed to already stumble my way through to a solution, and your suggestions confirm the approach I followed. Also, the linked resources are new to me, and helpful. Thanks again!
0

Just in case this helps future people, here is a dump of Lambda functions's code. It may not be structured perfectly, but it shows basic approach of what to do, to use JS SDK v.3 / Node v.18 on AWS and invoke "sub Lambdas":

Here is some code:

// Needs lambda execute IAM permission for each lambda, also.

import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";
const asciiDecoder = new TextDecoder('utf-8');

export const handler = async (event) => {
    const client = new LambdaClient();

    // https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-lambda/classes/invokecommand.html
    const fetchParams = {
        FunctionName: 'arn:aws:lambda:eu-north-1:880299674189:function:pv-estimate_fetchEstimate', // required
        // InvocationType: "Event" || "RequestResponse" || "DryRun",
        InvocationType: "RequestResponse",
        LogType: "Tail",
        // ClientContext: "STRING_VALUE",
        // Payload: "",
        // Qualifier: "STRING_VALUE",
    };


    const fetchCommand = new InvokeCommand(fetchParams);

    try {
        let retVal

        let response = await client.send(fetchCommand);
        // Payload comes back as array. Decode array and parse as json before returning data
        const estimate = JSON.parse(asciiDecoder.decode(response.Payload));

        const transformParams = {
            FunctionName: 'arn:aws:lambda:eu-north-1:880299674189:function:transformRecord', // required
            InvocationType: "RequestResponse",
            LogType: "Tail",
            Payload: JSON.stringify(estimate)
        };
        const transformCommand = new InvokeCommand(transformParams);
        response = await client.send(transformCommand);
        retVal = JSON.parse(asciiDecoder.decode(response.Payload));

        // API Gateway is picky about return payload format. https://stackoverflow.com/a/43718963/16824901
        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*", // Required for CORS support to work
                "Access-Control-Allow-Credentials": true // Required for cookies, authorization headers with HTTPS
            },
            body: JSON.stringify(retVal),
        }

    }
    catch (error) {
        console.error('Error invoking Lambda function:', error);
        return {
            statusCode: 500,
            body: 'Error invoking Lambda function'
        };
    }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.