typescriptamazon-web-servicesaws-lambdaaws-api-gateway

AWS Lambda Integration with API Gateway 502 errors


I have 2 simple GET requests in an API Gateway with Lambda Integrations. Both are simple Hello World type examples and the lambda code is almost identical - with the exception that one Lambda is Async and the other is not.

The Async one works fine, the non-Async call errors at the Api Gateway with a 502 error:

{
  "message": "Internal server error"
}

x-amzn-errortype    InternalServerErrorException

I am lost as to why this could be.

I have tracing and logging enabled in the API Gateway and I can see the logs which show the response as malformed:

Received response. Status: 200, 
Integration latency: 25 ms 
Method completed with status: 502 
Execution failed due to configuration error: Malformed Lambda proxy response 
Endpoint response body before transformations: null

Here is the code for both lambdas. The response is identical in each. Both lambdas have the same roles and permissions etc. Both response conform to the AWS required response format. Both Lambdas execute ok without error. The error is at the API Gateway side.

What could be causing this issue?

// works ok

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  console.log('Received event:', JSON.stringify(event, null, 2));
  // Example of a fake async operation
  await new Promise((resolve) => setTimeout(resolve, 0));

  const response: APIGatewayProxyResult = {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: 'Hello, World!',
      input: event,
    }),
  };

  return response;
};

// does not work:

import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';

export function handler(event: APIGatewayProxyEvent, context: Context): APIGatewayProxyResult {
  console.log('event', event);
  console.log('context', context);

  const response: APIGatewayProxyResult = {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message: 'Hello, World!',
      input: event,
    }),
  };

  return response;
}

Solution

  • The issue here seems to be that the synchronous Lambda is returning the response directly, rather than using a Promise, which is required when using AWS API Gateway with Lambda proxy integration. API Gateway expects the Lambda handler to return a Promise when it’s set up to use async behavior (either directly or by implicitly returning a Promise through the async keyword).

    In your synchronous Lambda function, try wrapping the response in a Promise.resolve() so that the API Gateway can handle the response properly. Here’s how to modify the second (synchronous) Lambda to fix the issue:

    import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
    
    export function handler(event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> {
      console.log('event', event);
      console.log('context', context);
    
      const response: APIGatewayProxyResult = {
        statusCode: 200,
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          message: 'Hello, World!',
          input: event,
        }),
      };
    
      // Wrap the response in a Promise to meet the async expectation of API Gateway
      return Promise.resolve(response);
    }
    

    Alternatively, you can switch the handler to use the async keyword, similar to your working Lambda.