Bug: exception_handler decorator won't return Response with botocore ClientError
See original GitHub issueExpected 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
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:13 (12 by maintainers)
Top Results From Across the Web
How to handle errors with boto3? - Stack Overflow
Use the response contained within the exception. Here is an example: import boto3 from botocore.exceptions import ClientError try: iam = boto3.client('iam') ...
Read more >Error handling — Boto3 Docs 1.26.35 documentation - AWS
The most common botocore exception you'll encounter is ClientError . This is a general exception when an error response is provided by an...
Read more >Handling Errors in Boto3 & Botocore - Trek10
ClientError: An error occurred (IllegalLocationConstraintException) when calling the CreateBucket operation: The unspecified location constraint is incompatible ...
Read more >How to use the botocore.exceptions function in ... - Snyk
To help you get started, we've selected a few botocore.exceptions examples, ... ClientError as error: raise BackupClientError(error.response) except ...
Read more >Guidelines for Ansible Amazon AWS module development
Fixing bugs; Adding new features; Migrating to boto3 ... For more information on botocore exception handling see the botocore error documentation.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Yes to the first question - we should handle ServiceError exceptions differently as customers will instinctively and eventually raise these to signal 4xx
On Tue, 26 Apr 2022 at 19:11, Stephan @.***> wrote:
Just that your
@app.exception_handler
should not swallow the passedex
, but thats just a tip in the docs 😛