title: Flask custom error handler not correctly handling registered error type
body: <p>I've created a basic Flask app and registered a custom error handler for a particular custom exception type. When this exception type is thrown and passed up the stack, however, Flask does not use the specified custom error handler.</p>
  
  <p>I've created a second error handler with the base Exception type, which successfully catches the error. The base exception handler's presence does not affect the custom error handler's ability to catch errors, if the base handler isn't present, the error bubbles all the way up to the default Flask 500 page.</p>
  
  <p>I've also done <code>print(srv.error_handler_spec)</code>, and it seems that the error handler is successfully being registered.</p>
  
  <p>Here is the main portion of <code>srv.py</code>, the entry point for my Flask app</p>
  
  <pre class="lang-py prettyprint-override"><code>from flask import Flask, request
  from flask import jsonify
  
  srv = Flask(__name__)
  
  class APIError(Exception):
      def __init__(self, message, status_code=500):
          Exception.__init__(self)
          self.message = message
          self.status_code = status_code
  
      def log_error(self):
          logging.error(f"API error: {self.to_json()}")
  
      def to_dict(self):
          return {"message": self.message, "status_code": self.status_code}
  
  
  @srv.errorhandler(Exception)
  def exception_handler(e: Exception):
      response = jsonify(
          {"message": f"unhandled exception encountered", "status_code": 500}
      )
      logging.error(f"unhandled exception encountered. type: {e.__class__}")
      response.status_code = 500
      return response
  
  
  @srv.errorhandler(APIError)
  def api_error_handler(e: APIError):
      response = jsonify(e.to_dict())
      response.status_code = e.status_code
      return response
  
  
  print(srv.error_handler_spec)
  
  
  @srv.route("/", methods=["GET"])
  def hello_world():
      return "hello world"
  
  
  @srv.route("/error", methods=["GET"])
  def error():
      raise APIError("generic error", status_code=400)
  </code></pre>
  
  <p>This is the log output from Flask when curling <code>/error</code></p>
  
  <pre><code>[32mapp_1      |[0m {None: {None: {&lt;class 'Exception'&gt;: &lt;function exception_handler at 0x7f211b8a5598&gt;, &lt;class 'srv.APIError'&gt;: &lt;function api_error_handler at 0x7f211b8a5620&gt;}}}
  [32mapp_1      |[0m {None: {None: {&lt;class 'Exception'&gt;: &lt;function exception_handler at 0x7f211b8a5e18&gt;, &lt;class '__main__.APIError'&gt;: &lt;function api_error_handler at 0x7f211b8a5ea0&gt;}}}
  [32mapp_1      |[0m  * Serving Flask app "srv" (lazy loading)
  [32mapp_1      |[0m  * Environment: production
  [32mapp_1      |[0m    WARNING: Do not use the development server in a production environment.
  [32mapp_1      |[0m    Use a production WSGI server instead.
  [32mapp_1      |[0m  * Debug mode: off
  [32mapp_1      |[0m  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
  [32mapp_1      |[0m ERROR:root:unhandled exception encountered. type: &lt;class 'srv.APIError'&gt;
  [32mapp_1      |[0m 172.27.0.5 - - [04/May/2019 06:52:47] "POST /api/user/create HTTP/1.1" 500 -
  [32mapp_1      |[0m INFO:werkzeug:172.27.0.5 - - [04/May/2019 06:52:47] "POST /api/user/create HTTP/1.1" 500 -
  [32mapp_1      |[0m 172.27.0.5 - - [04/May/2019 06:52:47] "GET /error HTTP/1.1" 400 -
  [32mapp_1      |[0m INFO:werkzeug:172.27.0.5 - - [04/May/2019 06:52:47] "GET /error HTTP/1.1" 400 -
  </code></pre>
  
  <p>As you can see from the log line <code>ERROR:root:unhandled exception encountered. type: &lt;class 'srv.APIError'&gt;</code> it's using the generic <code>Exception</code> handler and not the custom one for <code>APIError</code>.</p>
  
  <p>The expected behavior is that instead that Flask would instead use the custom error handler and print no log line at all.</p>
  
  <p>For the record, the results from <code>curl</code> are consistent with the generic error handler returning the response. This is definitely not an issue with the generic handler clobbering the more specific handler. (Although that would also be erroneous according to Flask's documentation).</p>
  
  <p>What gives?</p>