Skip to content

Commit 76aef1e

Browse files
Merge branch 'main' into fix/bound-method-entrypoint
2 parents 5818805 + 2e8a50a commit 76aef1e

2 files changed

Lines changed: 52 additions & 9 deletions

File tree

src/bedrock_agentcore/runtime/app.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,16 @@ async def _handle_invocation(self, request):
540540

541541
try:
542542
payload = await request.json()
543+
except json.JSONDecodeError as e:
544+
duration = time.time() - start_time
545+
self.logger.warning("Invalid JSON in request (%.3fs): %s", duration, e)
546+
return JSONResponse({"error": "Invalid JSON", "details": str(e)}, status_code=400)
547+
except UnicodeDecodeError as e:
548+
duration = time.time() - start_time
549+
self.logger.warning("Invalid encoding in request (%.3fs): %s", duration, e)
550+
return JSONResponse({"error": "Invalid encoding", "details": str(e)}, status_code=400)
551+
552+
try:
543553
self.logger.debug("Processing invocation request")
544554

545555
if self.debug:
@@ -584,15 +594,6 @@ async def _handle_invocation(self, request):
584594
# Use safe serialization for consistency with streaming paths
585595
safe_json_string = self._safe_serialize_to_json_string(result)
586596
return Response(safe_json_string, media_type="application/json")
587-
588-
except json.JSONDecodeError as e:
589-
duration = time.time() - start_time
590-
self.logger.warning("Invalid JSON in request (%.3fs): %s", duration, e)
591-
return JSONResponse({"error": "Invalid JSON", "details": str(e)}, status_code=400)
592-
except UnicodeDecodeError as e:
593-
duration = time.time() - start_time
594-
self.logger.warning("Invalid encoding in request (%.3fs): %s", duration, e)
595-
return JSONResponse({"error": "Invalid encoding", "details": str(e)}, status_code=400)
596597
except HTTPException as e:
597598
duration = time.time() - start_time
598599
# Use error level for 5xx to match the generic Exception handler's severity,

tests/bedrock_agentcore/runtime/test_app.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,48 @@ def handler(payload):
509509
assert response.status_code == 400
510510
assert "Invalid encoding" in response.json()["error"]
511511

512+
def test_handler_json_decode_error_returns_500_not_400(self):
513+
"""Test that JSONDecodeError raised inside the handler returns 500, not 400.
514+
515+
Regression test: previously, a broad except caught JSONDecodeError from
516+
both request parsing and handler logic, returning a misleading 400
517+
"Invalid JSON in request" for application-level parse failures.
518+
"""
519+
app = BedrockAgentCoreApp()
520+
521+
@app.entrypoint
522+
def handler(payload):
523+
import json
524+
525+
# Simulate parsing model output that isn't valid JSON
526+
json.loads("not valid json from model")
527+
528+
client = TestClient(app, raise_server_exceptions=False)
529+
response = client.post("/invocations", json={"input": "test"})
530+
531+
assert response.status_code == 500, f"Handler JSONDecodeError should return 500, got {response.status_code}"
532+
assert "Invalid JSON" not in response.json().get("error", ""), (
533+
"Handler JSONDecodeError should not say 'Invalid JSON' (that implies bad request)"
534+
)
535+
536+
def test_invalid_request_json_returns_400(self):
537+
"""Test that malformed JSON in the request body returns 400 with 'Invalid JSON'."""
538+
app = BedrockAgentCoreApp()
539+
540+
@app.entrypoint
541+
def handler(payload):
542+
return payload
543+
544+
client = TestClient(app, raise_server_exceptions=False)
545+
response = client.post(
546+
"/invocations",
547+
content=b"not valid json",
548+
headers={"content-type": "application/json"},
549+
)
550+
551+
assert response.status_code == 400
552+
assert "Invalid JSON" in response.json()["error"]
553+
512554
def test_return_response_passthrough(self):
513555
"""Test returning a Response object passes it through without wrapping."""
514556
from starlette.responses import JSONResponse

0 commit comments

Comments
 (0)