Search code examples
pythonflaskerror-handlingflask-restplus

Flask RestPlus: how to catch all exceptions and output the original error


I'm trying to catch all exceptions that may happen and output the stack details as message in FlaskRestPlus.

The below is an example that works if I raise custom exception such as RootException. But I didn't manage to get it to work with BaseException or anything else that might serve as a catch all. I also didn't find a way to output the stack (or original error message) into the message body.

@api.errorhandler(RootException)
def handle_root_exception(error):
    return {'message': 'Here I want the original error message'}, 500

Any suggestions how I can achieve this would be highly appreciated. THe documentation doesn't seem to be entirely clear: https://flask-restplus.readthedocs.io/en/stable/errors.html


Solution

  • To create a generic error handler, you can use:

    @api.errorhandler(Exception)
    def generic_exception_handler(e: Exception):
    

    Stack Trace Capturing

    To customize stack trace handling, see Python When I catch an exception, how do I get the type, file, and line number?.

    Example stack trace data capture

    import sys
    
    ...
    
    @api.errorhandler(Exception)
    def generic_exception_handler(e: Exception):
        exc_type, exc_value, exc_traceback = sys.exc_info()
    
        if exc_traceback:
            traceback_details = {
                'filename': exc_traceback.tb_frame.f_code.co_filename,
                'lineno': exc_traceback.tb_lineno,
                'name': exc_traceback.tb_frame.f_code.co_name,
                'type': get_type_or_class_name(exc_type),
                'message': str(exc_value),
            }
            return {'message': traceback_details['message']}, 500
        else:
            return {'message': 'Internal Server Error'}, 500
    

    The function get_type_or_class_name is a helper that gets the type name of an object, or in the case of a Class, returns the Class name.

    def get_type_or_class_name(var: Any) -> str:
        if type(var).__name__ == 'type':
            return var.__name__
        else:
            return type(var).__name__
    

    It is also customary to provide an HTTPException handler:

    from werkzeug.exceptions import HTTPException
    
    @api.errorhandler(HTTPException)
    def http_exception_handler(e: HTTPException):