This content is part of the Essential Guide: AWS Lambda architecture brings serverless to enterprise cloud

Tricks to dodge common AWS Lambda problems

Many cloud operations go off without a hitch, but there are errors that can gum up the works. That includes AWS Lambda functions, which are prone to several common miscues.

Some IT mistakes are just so common that there is no clear answer to prevent them. Omitting a parenthesis, forgetting...

to close a

tag in HTML or improperly handling Unicode in Python 2 could all result in an error message. But some mistakes you just have to identify after they happen. Know how to fix them before they become real problems.

With the introduction of AWS Lambda, the same old mistakes are still relevant. However, it can become even more complicated to identify them. When running code locally or even on an Elastic Compute Cloud (EC2) instance, it's easy to tail a log file and see error messages pertaining to what went wrong. But with event-driven computing, there is no physical or virtual server to log into, so it can be much more complicated to detect Lambda problems.

Developers can easily check code validity and syntax using a JavaScript monitoring tool like ESLint, but tracking down Lambda problems -- such as missing Amazon Identity and Access Management (IAM) permissions, unexpected input and even blocks of code exiting before calling the proper context callback -- can be much more complicated.

Process exited before completing request

One of the worst Lambda problems a developer can experience is the completely unhelpful message, "Process exited before completing request." It means that the code completed without calling anything on the "context" callback object. That could mean there's something in the code that's causing an exception, or it could mean the developer just forgot to call "context.done(err, msg)" after finishing the process.

This can be especially complicated with asynchronous code and multiple code paths. Make sure to catch any sort of errors or exceptions the code caused, log them appropriately and use "context.done(err)" to indicate any errors that should be retried. If an error occurred but it cannot be retried, such as a user-error in which the end user tried to upload invalid input, be sure to enter "context.done(null, errResponse)" -- otherwise the function can retry the call.

Permissions issues can be difficult to track down. Each time you encounter an issue, it may seem easiest to just give the IAM role that's running the Lambda function full access. Don't do it.

It's also a good idea to set up a log filter for the pattern "Process exited before completing request" and have it send an alert. If there are more than a few of those exits occurring, it probably means something is wrong with the code or it could mean the code is running too long. If the code is running too long, try increasing the timeout. Remember: The timeout can only be increased to five minutes.

Missing IAM permissions

Permissions issues can be difficult to track down. Each time you encounter an issue, it may seem easiest to just give the IAM role that's running the Lambda function full access. Don't do it.

Instead, think about running and testing code on an EC2 instance with that role. It's a good idea to log failed permissions to AWS in a third-party logging tool or in CloudWatch logs directly, and to set up alerts.

For example, in Node.js, if a developer uses the aws-sdk that comes automatically installed in Lambda, he will receive error messages like "[AccessDenied: Access Denied]". Make sure to check for error responses and log them from any AWS API call, which is always the first parameter in the callback you provide.

With DynamoDB or similar services, don't forget to grant access to tables and indexes. Developers can grant access to all indexes in a table using a wildcard operator.

Cached objects from a previous execution

A single instance of code may stick around between function executions. If code lives outside of the "handler" function, it's not guaranteed to run for every execution of the Lambda function. This code, for example, won't provide the current timestamp for each execution:

   var now = new Date();

   exports.handler = function(data, context){

     context.done(null, now.getTime());


In this code, the developer will probably get the same timestamp repeatedly until Lambda cleans up the function. Doing so can be incredibly helpful to reduce start-up time if you have resources that can be cached between executions. However, it's something to avoid if you're expecting a clean execution of the function every time it's called.

The correct way to write that function is illustrated below:

   exports.handler = function(data, context){

     var now = new Date();

     context.done(null, now.getTime());


Lambda functions calling Lambda functions?

It may seem odd, but a perfectly viable pattern is to have Lambda functions call other Lambda functions. The trick is to call the function asynchronously without having to wait for a response from other Lambda functions.

If a developer had them wait for responses, he would end up having a function spin its wheels -- doing nothing until another Lambda function completes. This is a massive waste of resources and ends up costing more than expected.

To trigger a function to operate asynchronously without waiting for the response, pass the InvocationType: 'Event':


     InvocationType: 'Event',

     FunctionName: ‘doSomething',

     Payload: JSON.stringify(payload),

   }, function(e, resp){


        // Probably means we didn't have permission



     context.done(null, resp);


Of course, make sure to not call context.done() until after the entire process is completed. After that point, the code will exit.

Run the correct versions

Node.js versions are at 5.0.0 now, but Lambda is running a version from before version 1.0.0. When the Node.js team partnered with the "fork" team that started IO.js, they worked hard to build what they considered a stable release version of Node.js. At this point, they've also committed to long-term support of Node.js, but Lambda is still very outdated.*

All of this happened within the last few months, so v0.10.36 was actually the previous LTS version; however, it's from January 2015. What changed since then? The Promises feature is now native, stack traces on asynchronous code and there have been several other minor performance improvements and stability fixes. Some npm modules may not even work on the older versions of Node, or they may function differently. Networking, in particular, seems to have undergone some stability improvements and can better detect Lambda problems when working with APIs over HTTP and HTTPS.

It is recommended to install and use Node Version Manager (NVM) and test code against the deployed version of Node.js in Lambda. NVM allows developers to install and use multiple different versions of Node.js and easily switch between them. Think of it like virtualenv for Node.

In addition, you'll need to use Python version 2.7. If a developer is working with Unicode or anything that uses Python 3 syntax or modules, it could lead to trouble.

*Lambda added support for Node.js 4.3. This is an improvement, as it adds support for native Promises, and it is the next big LTS Node.js version. But it's still over a year old, and a new version of Lambda is released every month. Developers using Lambda 4.3 should still use something like NVM to develop locally on the same version of Node running on Lambda.

Editor's Note: Since this article was first published, AWS added Step Functions, a service that coordinates serverless application workflows, including the use of functions to call other functions.

Next Steps

Lambda adds support for VPC, Python

Open source development tools team with Lambda

Microservices and Lambda can work together

Dig Deeper on AWS Lambda