Skip to content

Bug: exception_handler decorator won't return Response with botocore ClientError #1153

Closed
@sthuber90

Description

@sthuber90

Expected Behaviour

On botocore ClientError the Lambda function shall return:

{
  "statusCode": 400,
  "headers": {
    "Content-Type": "application/json"
  },
  "body": "{\"statusCode\": 400, \"message\": \"Bad Request\"}",
  "isBase64Encoded": false
}

Current Behaviour

Lambda function raises exception and ends with error, instead of returning HTTP response

Code snippet

import json
import boto3
from botocore.exceptions import ClientError

from aws_lambda_powertools.utilities.data_classes import (
    APIGatewayProxyEventV2,
    event_source,
)
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayHttpResolver, content_types
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.event_handler.exceptions import (
    BadRequestError,
    InternalServerError,
    NotFoundError,
)
from aws_lambda_powertools.event_handler.api_gateway import Response

logger = Logger()
app = APIGatewayHttpResolver()
dynamo = boto3.resource("dynamodb")


@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext):
    return app.resolve(event, context)

@app.get("/my/path")
def get_hello_universe():
    table = dynamo.Table("non-existent")
    table.get_item(
        Key={
            "pk": "abc",
            "sk": "123",
        },
    )
    return {"message": "hello universe"}
    

@app.exception_handler(ClientError)
def handle_botocore_error(ex: ClientError):
    metadata = {"path": app.current_event.path}
    logger.error(f"Exception: {ex}", extra=metadata)
    # return Response(
    #     status_code=400,
    #     content_type=content_types.APPLICATION_JSON,
    #     body=json.dumps({"statusCode": 400, "message": "Bad request"}),
    # )

    raise BadRequestError("something bad happened")

Possible Solution

No response

Steps to Reproduce

Use the provided code snippet to see that the Lambda will throw an exception instead of returning a 400 "Bad Request" response.

AWS Lambda Powertools for Python version

latest (Layer version 18)

AWS Lambda function runtime

3.9

Packaging format used

Lambda Layers

Debugging logs

START RequestId: 846da9eb-f64a-41e7-90cf-293386069384 Version: $LATEST
{"level":"ERROR","location":"handle_botocore_error:45","message":"Exception: An error occurred (AccessDeniedException) when calling the GetItem operation: User: arn:aws:sts::373270804851:assumed-role/test-role-hg1im76s/test is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:eu-central-1:373270804851:table/non-existent","timestamp":"2022-04-25 17:21:59,753+0000","service":"service_undefined","cold_start":true,"function_name":"test","function_memory_size":"128","function_arn":"arn:aws:lambda:eu-central-1:373270804851:function:test","function_request_id":"846da9eb-f64a-41e7-90cf-293386069384","correlation_id":"id","path":"/my/path","xray_trace_id":"1-6266d8b6-7c8a3e216f62498e0331a61a"}
[ERROR] BadRequestError: something bad happened
Traceback (most recent call last):
  File "/opt/python/aws_lambda_powertools/logging/logger.py", line 354, in decorate
    return lambda_handler(event, context)
  File "/opt/python/aws_lambda_powertools/middleware_factory/factory.py", line 134, in wrapper
    response = middleware()
  File "/opt/python/aws_lambda_powertools/utilities/data_classes/event_source.py", line 39, in event_source
    return handler(data_class(event), context)
  File "/var/task/lambda_function.py", line 28, in lambda_handler
    return app.resolve(event, context)
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 498, in resolve
    return self._resolve().build(self.current_event, self._cors)
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 557, in _resolve
    return self._call_route(route, match_results.groupdict())  # pass fn args
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 613, in _call_route
    response_builder = self._call_exception_handler(exc, route)
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 654, in _call_exception_handler
    return ResponseBuilder(handler(exp), route)
  File "/var/task/lambda_function.py", line 52, in handle_botocore_error
    raise BadRequestError("something bad happened")END RequestId: 846da9eb-f64a-41e7-90cf-293386069384
REPORT RequestId: 846da9eb-f64a-41e7-90cf-293386069384	Duration: 344.21 ms	Billed Duration: 345 ms	Memory Size: 128 MB	Max Memory Used: 67 MB	Init Duration: 630.48 ms

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions