Skip to content

Bug: Validating POST body fails with BedrockAgentResolver #3902

Closed
@rubenfonseca

Description

@rubenfonseca

Discussed in #3893

Originally posted by robk1234 March 6, 2024
What is the correct way to validate the POST body with BedrockAgent Resolver? I am getting a key error when I try with the following code:

from pydantic import EmailStr
from typing_extensions import Annotated

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import BedrockAgentResolver
from aws_lambda_powertools.event_handler.openapi.params import Body, Query
from aws_lambda_powertools.utilities.typing import LambdaContext


tracer = Tracer()
logger = Logger()

app = BedrockAgentResolver()


@app.post('/email', description="Validate an Email via post body")
def post_body_email(email: Annotated[EmailStr, Body(description="Email address to validate")],
         ) -> Annotated[bool, Body(description="returns true if I like the email")]:
    return True



@app.get('/email', description="Validate email via get request")
def get_email(email: Annotated[EmailStr, Query(description="Email address to validate")]
             )->Annotated[bool, Body(description="Returns True if I like the email")]:
    return True


@logger.inject_lambda_context
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext):
    return app.resolve(event, context)


if __name__ == "__main__":
    print(app.get_openapi_json_schema())

The GET Request works fine:

{
    "sessionId": "123456789012345",
    "sessionAttributes": {},
    "inputText": "Validate an email via get",
    "promptSessionAttributes": {},
    "apiPath": "/email",
    "parameters": [
      {
        "name": "email",
        "type": "string",
        "value": "[email protected]"
      }
    ],
    "agent": {
      "name": "TimeAgent",
      "version": "DRAFT",
      "id": "XLHH72XNF2",
      "alias": "TSTALIASID"
    },
    "httpMethod": "GET",
    "messageVersion": "1.0",
    "actionGroup": "SupportAssistant"
  }

Output is:

➜  test_lambda sam local invoke --event events/bedrock.json ApiFunction
Invoking app.lambda_handler (python3.12)                                                                                                                                                 
Local image is up-to-date                                                                                                                                                                
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.                                                                                                                       
                                                                                                                                                                                         
Mounting /Users/rklages/git/rob/test_lambda/.aws-sam/build/ApiFunction as /var/task:ro,delegated, inside runtime container                                                               
START RequestId: b783d02d-bb17-449b-b7c8-3671475fac6b Version: $LATEST
[WARNING]	2024-03-06T19:34:56.315Z	8bc618fb-4c0f-4847-9cb6-de8ddc744fb1	Subsegment ## lambda_handler discarded due to Lambda worker still initializing
[WARNING]	2024-03-06T19:34:57.013Z	8bc618fb-4c0f-4847-9cb6-de8ddc744fb1	No subsegment to end.
END RequestId: 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1
REPORT RequestId: 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1	Init Duration: 0.92 ms	Duration: 6873.37 ms	Billed Duration: 6874 ms	Memory Size: 128 MB	Max Memory Used: 128 MB	
{"messageVersion": "1.0", "response": {"actionGroup": "SupportAssistant", "apiPath": "/email", "httpMethod": "GET", "httpStatusCode": 200, "responseBody": {"application/json": {"body": "true"}}}}

With the POST payload:

{
  "sessionId": "123456789012345",
  "sessionAttributes": {},
  "inputText": "Please validate email [email protected] via POST",
  "promptSessionAttributes": {},
  "apiPath": "/email",
  "requestBody": {
      "application/json": {
        "properties": [
          {
            "name": "email",
            "type": "string",
            "value": "[email protected]"
          }
        ]
      }

  },
  "agent": {
    "name": "TimeAgent",
    "version": "DRAFT",
    "id": "XLHH72XNF2",
    "alias": "TSTALIASID"
  },
  "parameters": [],
  "httpMethod": "POST",
  "messageVersion": "1.0",
  "actionGroup": "SupportAssistant"
}

I'm getting the following error:

➜  test_lambda sam local invoke --event events/bedrock_post.json ApiFunction
Invoking app.lambda_handler (python3.12)                                                                                                                                                 
Local image is up-to-date                                                                                                                                                                
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.                                                                                                                       
                                                                                                                                                                                         
Mounting /Users/rklages/git/rob/test_lambda/.aws-sam/build/ApiFunction as /var/task:ro,delegated, inside runtime container                                                               
START RequestId: d785f329-b65b-4ef1-b55c-2c91e4adbd5d Version: $LATEST
[WARNING]	2024-03-06T19:36:01.835Z	7d6e024a-be8d-495d-976f-c30fc60cf218	Subsegment ## lambda_handler discarded due to Lambda worker still initializing
[WARNING]	2024-03-06T19:36:02.177Z	7d6e024a-be8d-495d-976f-c30fc60cf218	No subsegment to end.
LAMBDA_WARNING: Unhandled exception. The most likely cause is an issue in the function code. However, in rare cases, a Lambda runtime update can cause unexpected function behavior. For functions using managed runtimes, runtime updates can be triggered by a function change, or can be applied automatically. To determine if the runtime has been updated, check the runtime version in the INIT_START log entry. If this error correlates with a change in the runtime version, you may be able to mitigate this error by temporarily rolling back to the previous runtime version. For more information, see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html
[ERROR] KeyError: 'body'
Traceback (most recent call last):
  File "/var/task/aws_lambda_powertools/logging/logger.py", line 447, in decorate
    return lambda_handler(event, context, *args, **kwargs)
  File "/var/task/aws_lambda_powertools/tracing/tracer.py", line 313, in decorate
    response = lambda_handler(event, context, **kwargs)
  File "/var/task/app.py", line 34, in lambda_handler
    return app.resolve(event, context)
  File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1815, in resolve
    response = self._resolve().build(self.current_event, self._cors)
  File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1922, in _resolve
    return self._call_route(route, route_keys)  # pass fn args
  File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 2000, in _call_route
    route(router_middlewares=self._router_middlewares, app=self, route_arguments=route_arguments),
  File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 400, in __call__
    return self._middleware_stack(app)
  File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1291, in __call__
    return self.current_middleware(app, self.next_middleware)
  File "/var/task/aws_lambda_powertools/event_handler/middlewares/base.py", line 121, in __call__
    return self.handler(app, next_middleware)
  File "/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py", line 105, in handler
    received_body=self._get_body(app),
  File "/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py", line 230, in _get_body
    return app.current_event.json_body
  File "/var/lang/lib/python3.12/functools.py", line 995, in __get__
    val = self.func(instance)
  File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 153, in json_body
    return self._json_deserializer(self.decoded_body)
  File "/var/lang/lib/python3.12/functools.py", line 995, in __get__
    val = self.func(instance)
  File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 158, in decoded_body
    body: str = self["body"]
  File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 32, in __getitem__
    return self._data[key]
END RequestId: 7d6e024a-be8d-495d-976f-c30fc60cf218
REPORT RequestId: 7d6e024a-be8d-495d-976f-c30fc60cf218	Init Duration: 0.89 ms	Duration: 6576.10 ms	Billed Duration: 6577 ms	Memory Size: 128 MB	Max Memory Used: 128 MB	
{"errorMessage": "'body'", "errorType": "KeyError", "requestId": "7d6e024a-be8d-495d-976f-c30fc60cf218", "stackTrace": ["  File \"/var/task/aws_lambda_powertools/logging/logger.py\", line 447, in decorate\n    return lambda_handler(event, context, *args, **kwargs)\n", "  File \"/var/task/aws_lambda_powertools/tracing/tracer.py\", line 313, in decorate\n    response = lambda_handler(event, context, **kwargs)\n", "  File \"/var/task/app.py\", line 34, in lambda_handler\n    return app.resolve(event, context)\n", "  File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1815, in resolve\n    response = self._resolve().build(self.current_event, self._cors)\n", "  File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1922, in _resolve\n    return self._call_route(route, route_keys)  # pass fn args\n", "  File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 2000, in _call_route\n    route(router_middlewares=self._router_middlewares, app=self, route_arguments=route_arguments),\n", "  File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 400, in __call__\n    return self._middleware_stack(app)\n", "  File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1291, in __call__\n    return self.current_middleware(app, self.next_middleware)\n", "  File \"/var/task/aws_lambda_powertools/event_handler/middlewares/base.py\", line 121, in __call__\n    return self.handler(app, next_middleware)\n", "  File \"/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py\", line 105, in handler\n    received_body=self._get_body(app),\n", "  File \"/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py\", line 230, in _get_body\n    return app.current_event.json_body\n", "  File \"/var/lang/lib/python3.12/functools.py\", line 995, in __get__\n    val = self.func(instance)\n", "  File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 153, in json_body\n    return self._json_deserializer(self.decoded_body)\n", "  File \"/var/lang/lib/python3.12/functools.py\", line 995, in __get__\n    val = self.func(instance)\n", "  File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 158, in decoded_body\n    body: str = self[\"body\"]\n", "  File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 32, in __getitem__\n    return self._data[key]\n"]}
```</div>

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions