Repository navigation
Bug: exception handlers hijack the default 404 and bypass _to_response (body null on ALB, dict/tuple crash) #8579
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't workingevent_handlersgood first issueGood for newcomersGood for newcomerspending-releaseFix or implementation already in dev waiting to be releasedFix or implementation already in dev waiting to be released
Milestone
Description
Expected Behaviour
- An unmatched route returns 404 even when a broad
@app.exception_handler(Exception)is registered. - Whatever an exception handler returns goes through the same
_to_responseadaptation as a route return value, soResponse(body=None)on ALB becomes""and a dict/tuple is converted or rejected clearly.
Current Behaviour
All in api_gateway.py, confirmed through a real API Gateway REST API:
- 404 hijacked.
not_found_handler(line 2847) synthesizes aNotFoundError()that was never raised and looks it up withlookup_exception_handler, which walks the MRO. With@app.exception_handler(Exception), which the docs suggest as a catch-all, every unmatched route returns 500:GET /nope→500 generic handler got NotFoundError(). body: nullon ALB._call_exception_handler(line 2952) wrapshandler(exp)directly in the response builder. OnALBResolver, a handler returningResponse(status_code=400, body=None)emits"body": nulland ALB answers 502. The sameResponsereturned from a route emits""because_to_responsefixes it.- dict/tuple return crashes. A handler returning
{"error": str(exc)}, 400raisesAttributeError: 'tuple' object has no attribute 'is_json', masking the original exception. Real API: 502.
Code snippet
from aws_lambda_powertools.event_handler import ALBResolver, APIGatewayRestResolver, Response
from tests.functional.utils import load_event
ev = load_event("apiGatewayProxyEvent.json") # GET /my/path
app = APIGatewayRestResolver()
@app.exception_handler(Exception)
def generic(exc):
return Response(500, "text/plain", f"generic got {exc!r}")
@app.get("/other")
def other():
return {}
print(app.resolve(ev, None)) # statusCode 500, body "generic got NotFoundError()" (expected 404)
alb = ALBResolver()
@alb.exception_handler(ValueError)
def h(exc):
return Response(status_code=400, content_type=None, body=None)
@alb.get("/lambda")
def r():
raise ValueError("x")
print(alb.resolve(load_event("albEvent.json"), None)["body"]) # None (expected "")
app2 = APIGatewayRestResolver()
@app2.exception_handler(ValueError)
def h2(exc):
return {"error": str(exc)}, 400
@app2.get("/my/path")
def r2():
raise ValueError("boom")
app2.resolve(ev, None) # AttributeError: 'tuple' object has no attribute 'is_json'Possible Solution
In not_found_handler, look up only an exact NotFoundError registration instead of walking the MRO. In _call_exception_handler, wrap the handler result with self._to_response(handler(exp)).
Steps to Reproduce
Run the snippet above with the tests/events fixtures. Full context in #8576.
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.13
Packaging format used
PyPi
Debugging logs
Warning
This issue is ready to be picked up, by humans or by agents. If you want it, comment here first so we can assign it to you, and please take only one or two issues at a time so others can join in too. Thanks!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingevent_handlersgood first issueGood for newcomersGood for newcomerspending-releaseFix or implementation already in dev waiting to be releasedFix or implementation already in dev waiting to be released
Type
Projects
- StatusShow more project fieldsComing soon
Activity
MrNK2107 commentedon Oct 18, 2026
Hi @leandrodamascena, I'd like to work on this one. Plan:
not_found_handler, only use a handler registered forNotFoundErroritself, so a catch-all@app.exception_handler(Exception)no longer turns unmatched routes into 500s._to_response, soResponse(body=None)on ALB becomes""and dict/tuple returns are adapted the same way as route return values.Could you assign it to me?
leandrodamascena commentedon Oct 18, 2026
Hey @MrNK2107 pls go ahead
fix(event_handler): keep catch-all handlers off 404s and adapt except…
powertools-for-aws-oss-automation commentedon Oct 22, 2026
Warning
This issue is now closed. Please be mindful that future comments are hard for our team to see.
If you need more assistance, please either reopen the issue, or open a new issue referencing this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.
fix(event_handler): keep catch-all exception handlers off 404s and ad…