DEV Community


Debugging Serverless API Issues

Salah Elhossiny
ML engineer || AWS Certified MLS || AWS Community Builders member || Fullstack developer
・4 min read

In this article we are going to take a brief look at some common API Gateway and Lambda issues we come across and how to debug them.

When a request is made to your serverless API, it starts by hitting API Gateway and makes its way through to Lambda and invokes your function. It takes quite a few hops along the way and each hop can be a point of failure. And since we don’t have great visibility over each of the specific hops, pinpointing the issue can be a bit tricky.

We are going to take a look at the following issues:

Invalid API Endpoint
Missing IAM Policy
Lambda Function Error
Lambda Function Timeout

Invalid API Endpoint

The first and most basic issue we see is when the API Gateway endpoint that is requested is invalid.

An API Gateway endpoint usually looks something like this:
Enter fullscreen mode Exit fullscreen mode

• API_ID - a unique identifier per API Gateway project
• REGION - the AWS region in which the API Gateway project is deployed to.
• STAGE - the stage of the project (defined in your serverless.yml or passed in through the serverless deploy –stage command).
• PATH - the path of an API endpoint (defined in your serverless.yml for each function)

An API request will fail if:

• The API_ID is not found in the specified REGION
• The API Gateway project does not have the specified STAGE
• API endpoint invoked does not match a pre-defined PATH

In all of these cases, the error does not get logged to CloudWatch since the request does not hit your API Gateway project.

Missing IAM Policy

This happens when your API endpoint uses aws_iam as the authorizer, and the IAM role assigned to the Cognito Identity Pool has not been granted the execute-api:Invoke permission for your API Gateway resource.

This is a tricky issue to debug because the request still has not reached API Gateway, and hence the error is not logged in the API Gateway CloudWatch logs. But we can perform a check to ensure that our Cognito Identity Pool users have the required permissions, using the IAM policy Simulator.

Before we can use the simulator we first need to find out the name of the IAM role that we are
using to connect to API Gateway.

  • Select Cognito from your AWS Console.
  • Next hit the Manage Federated Identities button.
  • And select your Identity Pool.
  • Click Edit identity pool at the top right.
  • Now that we know the IAM role we are testing, let’s open up the IAM Policy Simulator.
  • Select Roles.
  • Select the IAM role that we made a note of in the steps above.
  • Select API Gateway as the service and select the Invoke action.
  • Expand the service and enter the API Gateway endpoint ARN, then select Run Simula on.

  • If your IAM role is configured properly you should see allowed under Permission. But if something is off, you’ll see denied.

  • To fix this and edit the role we need to go back to the AWS Console and select IAM from the list of services.

  • Select Roles on the left menu.

  • And select the IAM role that our Identity Pool is using.

  • Expand the policy under the list of policies.

  • Click Edit policy.

Here you can edit the policy to ensure that it has the right permission to invoke API Gateway.
Ensure that there is a block in your policy like the one below.

  "Effect": "Allow",
  "Action": [
  "Resource": [
Enter fullscreen mode Exit fullscreen mode

Finally, hit Save to update the policy.

Now if you test your policy, it should show that you are allowed to invoke your API Gateway endpoint.

Lambda Function Error

Now if you are able to invoke your Lambda function but it fails to execute properly due to uncaught exceptions, it’ll error out. These are pretty straightforward to debug.

When this happens, AWS Lambda will attempt to convert the error object to a string, and then send it to CloudWatch along with the stacktrace. This can be observed in both Lambda and API Gateway CloudWatch log groups.

Lambda Function Timeout

Sometimes we might run into a case where the Lambda function just times out. Normally, a Lambda function will end its execution by invoking the callback function that was passed in.

By default, the callback will wait until the Node.js runtime event loop is empty before returning the results to the caller.

If the Lambda function has an open connection to, let’s say a database server, the event loop is not empty, and the callback will wait indefinitely until the connection is
closed or the Lambda function times out.

To get around this issue, you can set this callbackWaitsForEmptyEventLoop property to false to request AWS Lambda to freeze the process as soon as the callback is called, even if there are events in the event loop.

export async function handler(event, context, callback) {
   context.callbackWaitsForEmptyEventLoop = false;
Enter fullscreen mode Exit fullscreen mode

This effectively allows a Lambda function to return its result to the caller without requiring that the database connection be closed. This allows the Lambda function to reuse the same connection across calls, and it reduces the execution time as well.

These are just a few of the common issues we see folks running into while working with serverless APIs.


ServerlessStack framework

Discussion (0)