3

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

Christopher Peisert
  • 21,862
  • 3
  • 86
  • 117
Nickpick
  • 6,163
  • 16
  • 65
  • 116

1 Answers1

3

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):
Christopher Peisert
  • 21,862
  • 3
  • 86
  • 117
  • @Nickpick See updated answer with definition of `get_type_or_class_name`. – Christopher Peisert Jul 23 '19 at 12:24
  • 1
    This works great in debug mode, but it doesn't seem to work if it's in production mode (i.e. flask not in debug or run with iis). Any suggestions what I can do about that? – Nickpick Jul 25 '19 at 16:16