-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error handler call order is not deterministic #202
Comments
What's the use case for having 2 error handler functions with the same name (i.e. |
It was a typo, I just corrected it. |
In that case, I don't see why raising |
Registering an error handler for an exception will also catch child exceptions, see flask-restx/flask_restx/api.py Line 674 in 66d884f
Where the exception being raised is validated with isinstance . I'll update the snippet of that isn't clear, thanks for your response. |
In your example, both classes only are subclass of Exception. However, I can see where there would be a problem if SomeSpecificError is a subclass GenericError: class GenericError(Exception):
pass
class SomeSpecificError(GenericError):
pass
ns = Namespace("some_route")
@ns.errorhandler(SomeSpecificError)
def handle_specific_error(error):
return {"message": "something specific happened"}, 401
@ns.errorhandler(GenericError)
def handle_generic_error(error):
return {"message": "generic error"}, 401 Based on flask-restx/flask_restx/api.py Line 673 in 66d884f
I see that given The proposed solution of checking the handlers in the order they were registered would work in scenarios where more specific handlers are registered before less specific handlers: @ns.errorhandler(SomeSpecificError)
def handle_specific_error(error):
return {"message": "something specific happened"}, 401
@ns.errorhandler(GenericError)
def handle_generic_error(error):
return {"message": "generic error"}, 401 But if we reverse the order the handlers are registered in, the bug would still be encountered: @ns.errorhandler(GenericError)
def handle_generic_error(error):
return {"message": "generic error"}, 401
@ns.errorhandler(SomeSpecificError)
def handle_specific_error(error):
return {"message": "something specific happened"}, 401 What do you think about adding "exact match" type check? Something like for typecheck, handler in six.iteritems(self._own_and_child_error_handlers):
if type(e, typecheck):
# Found exact match to handle error
result = handler(e)
default_data, code, headers = unpack(
result, HTTPStatus.INTERNAL_SERVER_ERROR
)
break
elif isinstance(e, typecheck):
# Found subclass to handle error,
# keep looking for an exact match or a superseding subclass
candidate_handler = handler
# No exact match found. If subclass match was found, use it
if candidate_handler:
result = candidate_handler(e)
default_data, code, headers = unpack(
result, HTTPStatus.INTERNAL_SERVER_ERROR
) The OrderedDict would still ensure consistent behavior when there is no exact match registered for the exception and multiple subclasses match. In this case, the last handler registered that is a match would be chosen to handle the error. |
I corrected the code sample in the original issue which probably caused the confussion, I'm very sorry. Yes, I meant to state that I only want to correct an error we did see that is clearly present, the fact that the order of error handlers is not predictable and we are seeing intermittent errors in our tests due to this. My proposed fix is minimal and is in any case, required to make the order predictable. I don't think I would want to alter the behavior much more. |
Code
Here is sample code where the issue is seen
Repro Steps (if applicable)
Expected Behavior
the order in which the error handlers are registered should be taken into account when those are looked up for a given exception
Actual Behavior
Handlers are called in non deterministic order
Environment
The text was updated successfully, but these errors were encountered: