ValidationError causes HTTP/500 in Flask instead of HTTP/422 in Python 2
See original GitHub issueHere are the symptoms: http://stackoverflow.com/questions/37321835/flask-error-handler-not-able-to-handle-assertion-error/39624893#39624893
Here is the case where I personally hit the issue with Python 2.x and PyPy in Python 2.x mode only: https://travis-ci.org/frol/flask-restplus-server-example/builds/161685419
After troubleshooting, I discovered that this issue stems from the FlaskParser.handle_error
which calls abort
function with exc=
argument, which then is set as “data” on the raised HTTPException
, which in its turn is tried to be json-dumped and fails with TypeError
, and now the new exception is in sys.exc_info()
, which causes Flask to assert here.
Searching git history for the introduced exc=
in FlaskParser
, I found it here: https://github.com/sloria/webargs/commit/6f8088c7c85c05d2891e81ee97d38f2ae801159d
Is there a reason for exc=
to be passed? How can we fix this?
Python 3 seems to have changed something with sys.exc_info()
behaviour since even after the TypeError
caused by json.dumps()
, sys.exc_info()
still reports HTTPException
while in Python 2 it returns TypeError
.
Issue Analytics
- State:
- Created 7 years ago
- Comments:8 (3 by maintainers)
Top GitHub Comments
I took the option 1 in my project: https://github.com/frol/flask-restplus-server-example/blob/8118f66e3c9c505da1b92f3373c4b3c583af3bf6/app/extensions/api/webargs_parser.py
I am not sure how this can be handled in a better way, so if you happen to find a better solution, please, share.
Here is what happened before my fix:
handle_error
is calledhandle_error
calledabort(status_code, messages=error.messages, exc=error)
abort
patches the HTTPException passing all**kwargs
(messages
andexc
) toHTTPException.data
data
, and tries to serialize it to JSONjson.dumps
fails because it cannot serializeexc
object passed throughabort
(steps 4-5)TypeError
) and passes this handling to yourapp.error_handler
, and here the Python 2 and Python 3 difference jumps in, Python 3 has the long story of exceptions and the original exception was HTTPException/422, but Python 2 overrides this info with the latest JSON-Encode-Error (TypeError
) and, as a result, you have HTTP/500.In any case, Webargs
abort
implementation didn’t work, it led to the JSON-Encode-Error exception which was handled expectedly on Python 3 only by a pure luck.