I am trying to start learning serverless / lambda so I created a simple lambda and deployed it with serverless which worked.
However when I want to test the endpoint of the lampbda I get a 502 back. When I look in the logs it tells me that it can not find the module handler which does not make any sense...
here is the log:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'handler'\nRequire stack:\n-
/var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'handler'",
"Require stack:",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:1158:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)",
" at Module.load (internal/modules/cjs/loader.js:1002:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:901:14)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)",
" at internal/main/run_main_module.js:18:47"
]
}
This normally means that it can not find the method that is the starting point to execute.
For example on your serverless.yml you can have something like this
functions:
getUsers:
handler: userFile.handler
this would mean that it's required to have a userFile in the same folder of the serverless.yml with the method handler exported.
module.exports.hello = async event => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
},
null,
2
),
};
};
Note that it does not need to be named handler function, just needs to have the same name defined on the serverless.yml
I ran into the same error when launching a lambda locally using AWS sam, with Webstorm.
Turns out a previous run had not correctly stopped and destroyed the docker container running the lambda. Stopping and removing said docker container fixed the problem for me.
Related
This is the code:
/* global AWS */
AWS.config.update({region: 'us-east-1'});
const ssm = new AWS.SSM();
console.log('Loading function...');
exports.handler = async (event, context) => {
//console.log('Received event:', JSON.stringify(event, null, 2));
console.log('value1 =', event.key1);
console.log('value2 =', event.key2);
console.log('value3 =', event.key3);
ssm.getParameters({
Names: [`/my/dev/scrt`],
WithDecryption: false,
}).promise()
.then(data => data.Parameters.length ? data.Parameters[0].Value : Promise.reject(new Error(`SSM Parameter was not set.`)))
.then(plainsecret => {
console.log(`the secret is ${scrt}`);
return `${scrt} - ${event.key1}`; // Echo back the first key value
});
};
The error:
Response
{
"errorType": "ReferenceError",
"errorMessage": "AWS is not defined",
"trace": [
"ReferenceError: AWS is not defined",
" at Object.<anonymous> (/var/task/index.js:2:1)",
" at Module._compile (internal/modules/cjs/loader.js:1085:14)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)",
" at Module.load (internal/modules/cjs/loader.js:950:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:790:12)",
" at Module.require (internal/modules/cjs/loader.js:974:19)",
" at require (internal/modules/cjs/helpers.js:101:18)",
" at _tryRequireFile (/var/runtime/UserFunction.js:72:32)",
" at _tryRequire (/var/runtime/UserFunction.js:160:20)",
" at _loadUserApp (/var/runtime/UserFunction.js:219:12)"
]
}
Function Logs
[AWS Parameters and Secrets Lambda Extension] 2023/02/14 17:45:26 PARAMETERS_SECRETS_EXTENSION_LOG_LEVEL is not present. Log level set to info.
I thought /* global AWS */ was how you made the aws module available to lambda. Seems it doesn't work? Also, I added the layer AWS-Parameters-and-Secrets-Lambda-Extension, version 4, merge order 1. So again not sure why it's complaining?
Adding a comment in your code of /* global AWS */ doesn't magically provide anything. However the AWS SDK for NodeJS is included in the NodeJS Lambda runtime. Also, you don't need the AWS-Parameters-and-Secrets-Lambda-Extension if you are just using the standard AWS SDK to pull a secret value, as you appear to be doing.
Assuming you are using NodeJS 16 or earlier, with the AWS SDK v2 (which is what your code looks like) then you simply need to add the following line to the top of your file:
var AWS = require("aws-sdk");
If you are using NodeJS 18, then it comes with the AWS SDK v3, and you need to follow this guide to using it.
When I upload lambda layer through console, the module is found when the lambda runs, but when I deploy the same layer through the cdk, it's not found.
lambda > Runtime.NODEJS_16_X
layer > node-fetch#2.6.7
Through the cdk:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'node-fetch'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/index.mjs",
"stack": [
"Runtime.ImportModuleError: Error: Cannot find module 'node-fetch'",
"Require stack:",
"- /var/task/index.js",
"- /var/runtime/index.mjs",
" at _loadUserApp (file:///var/runtime/index.mjs:1000:17)",
" at async Object.UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)",
" at async start (file:///var/runtime/index.mjs:1200:23)",
" at async file:///var/runtime/index.mjs:1206:1"
]
}
This is part of a bigger solution being deployed in through a cdk pipeline, and it's getting blocked here.
I have a REST API built using NestJS and I'm trying to deploy this to AWS Lambda.
I've created a file called serverless.ts in the src directory of my app -
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
import serverlessExpress from '#vendia/serverless-express';
import { Handler, Callback, Context } from 'aws-lambda';
let server: Handler;
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
}
bootstrap();
export const handler: Handler = async (
event: any,
context: Context,
callback: Callback,
) => {
server = server ?? (await bootstrap());
return server(event, context, callback);
};
Now, when I tried deploying this app/handler to AWS Lambda using Serverless framework, it failed a couple of times due to big package size (Lambda limits it to 250Mb).
The next option I had was to use docker and Elastic Container Registry (AWS ECR) to upload an image to Lambda.
Dockerfile -
FROM public.ecr.aws/lambda/nodejs:14
COPY package*.json ${LAMBDA_TASK_ROOT}
RUN npm install
COPY . ${LAMBDA_TASK_ROOT}
RUN npm run build
CMD [ "dist/serverless.handler" ]
I build this image and push to ECR Repository using the following commands -
aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com
docker tag e9ae3c220b23 aws_account_id.dkr.ecr.region.amazonaws.com/my-repository:tag
docker push aws_account_id.dkr.ecr.region.amazonaws.com/my-repository:tag
The push is successful now. Then I import this image to AWS Lambda and add a API Gateway Trigger to generate an HTTP endpoint.
When I try to access this endpoint, it says -
{ message: Internal server error }
When I view logs in Cloudwatch, this is what I see -
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'serverless'\nRequire stack:\n- /var/runtime/UserFunction.js\n- /var/runtime/Runtime.js\n- /var/runtime/index.js",
"stack": [
"Runtime.ImportModuleError: Error: Cannot find module 'serverless'",
"Require stack:",
"- /var/runtime/UserFunction.js",
"- /var/runtime/Runtime.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:221:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:279:17)",
" at Object. (/var/runtime/index.js:43:34)",
" at Module._compile (internal/modules/cjs/loader.js:1085:14)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)",
" at Module.load (internal/modules/cjs/loader.js:950:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:790:12)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)",
" at internal/main/run_main_module.js:17:47"
]
}
I am unable to figure out the root cause and a fix for this issue. How do I resolve this?
I want package a lambda layer using codebuild.
My codebuild buildspec is as follows:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
commands:
- npm init -y
- npm install --save middy
artifacts:
files:
- 'node_modules/**/*'
- 'package-lock.json'
- 'package.json'
This saves a nodejs.zip folder to my s3 bucket
the resulting zip file looks like this:
package.json is as follows:
{
"name": "src",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"middy": "^0.30.4"
}
}
however when I add this layer to my lambda (node10.x)
and import my mods:
'use strict';
var AWS = require('aws-sdk');
const middy = require('middy')
const { cors } = require('middy/middlewares')
Returns the following error:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'middy'\nRequire stack:\n- /var/task/function_code/verify_zipcode.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'middy'",
"Require stack:",
"- /var/task/function_code/verify_zipcode.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:956:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)",
" at Module.load (internal/modules/cjs/loader.js:812:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:724:14)",
" at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)",
" at internal/main/run_main_module.js:17:11"
]
}
Adding the envoronment variable:
NODE_PATH : ./:/opt/node_modules gave my lambda access to my layers, but lost the context of aws-sdk
After adding the env var I get the following error:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'aws-sdk'\nRequire stack:\n- /var/task/function_code/verify_zipcode.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'aws-sdk'",
"Require stack:",
"- /var/task/function_code/verify_zipcode.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:956:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)",
" at Module.load (internal/modules/cjs/loader.js:812:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:724:14)",
" at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)",
" at internal/main/run_main_module.js:17:11"
]
}
Is there a way to use both the native aws-sdk and my layers? Or do I need to use an aws-sdk layer anytime I use other custom layers?
The directory structure of a node.js layer (nodejs.zip in your example) should be:
├── nodejs
└── package.json
└── node_modules
└── middy(version z.z.z)
Update your buildspec file to add a parent nodejs folder:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
commands:
- mkdir nodejs # NEW LINE
- cd nodejs # NEW LINE
- npm init -y
- npm install bcrypt
artifacts:
files:
- 'nodejs/**/*' # CHANGE LINE
- 'package.json'
and remove the environment variable:
NODE_PATH
I'm trying to get Netlify Functions work with Go.
First, I tried cloning official example repo (https://github.com/netlify/aws-lambda-go-example) and it worked.
My problem is, I have a Hugo website which require hugo build command and I don't know how to build Hugo with hugo and Go source files with make build (like in example repo) - I think it could solve the problem, but I couldn't find relevant docs describing this option.
So my next step was to manually compile Go function file and put it into functions folder.
source file (from the example above):
package main
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return events.APIGatewayProxyResponse{
StatusCode: 200,
Body: "Hello AWS Lambda and Netlify",
}, nil
}
func main() {
// Make the handler available for Remote Procedure Call by AWS Lambda
lambda.Start(handler)
}
I used instruction available at https://github.com/aws/aws-lambda-go#building-your-function to compile Go binary:
GOOS=linux GOARCH=amd64 go build -o hello hello.go
zip hello.zip hello
mv hello.zip ./functions/hello.zip
This was pushed to Git and therefore deployed to Netlify. So far so good, my function appeared in Netlify UI.
But when I requested the function URL, I got error message:
{
"errorMessage": "Invalid or unexpected token",
"errorType": "SyntaxError",
"stackTrace": [
"",
"SyntaxError: Invalid or unexpected token",
"createScript (vm.js:80:10)",
"Object.runInThisContext (vm.js:139:10)",
"Module._compile (module.js:616:28)",
"Object.Module._extensions..js (module.js:663:10)",
"Module.load (module.js:565:32)",
"tryModuleLoad (module.js:505:12)",
"Function.Module._load (module.js:497:3)",
"Module.require (module.js:596:17)",
"require (internal/module.js:11:18)"
]
}
This is function log from Netlify:
1:18:16 AM: hello invoked
1:18:17 AM: Syntax error in module 'hello': SyntaxError
(function (exports, require, module, __filename, __dirname) { ELF
^
SyntaxError: Invalid or unexpected token
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
1:19:02 AM: hello invoked
1:19:03 AM: Syntax error in module 'hello': SyntaxError
^
SyntaxError: Invalid or unexpected token
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
Also, function name appears to be hello.js in Netlify UI - I don't know if it should be like that. It seems to me that AWS thinks it's Javascript instead of Go.
I have not tested a zipped go function on Netlify.
If you do not want to do the manual build in this case, you can inline your build commands on Netlify deploy.
Add a build command that does both builds for the project.
[build]
command = "make build && hugo"
functions = "functions"
publish = "public"
[build.environment]
# Change this path with the path to your repository
GO_IMPORT_PATH = "github.com/netlify/aws-lambda-go-example"