Skip to content

Commit

Permalink
handle an exception without a traceback
Browse files Browse the repository at this point in the history
When an exception does not have a traceback there are no frames
to filter, but there's an explicit check for the last frame which
will fail if there are no frames.

An example exception with this problem can be seen when using
concurrent.futures.ProcessPoolExecutor.  When it reconstitutes a
remote exception it has serialized the traceback to a string it
includes as the error message instead of an object that can be
inspected.
  • Loading branch information
kjurka authored and davidism committed Oct 6, 2021
1 parent c7deb75 commit a026095
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -39,6 +39,9 @@ Unreleased
- Fix setting CSP header options on the response. :pr:`2237`
- Fix an issue with with the interactive debugger where lines would
not expand on click for very long tracebacks. :pr:`2239`
- The interactive debugger handles displaying an exception that does
not have a traceback, such as from ``ProcessPoolExecutor``.
:issue:`2217`


Version 2.0.1
Expand Down
5 changes: 5 additions & 0 deletions src/werkzeug/debug/tbtools.py
Expand Up @@ -357,6 +357,11 @@ def __init__(
tb = tb.tb_next # type: ignore

def filter_hidden_frames(self) -> None:
# An exception may not have a traceback to filter frames, such
# as one re-raised from ProcessPoolExecutor.
if not self.frames:
return

new_frames: t.List[Frame] = []
hidden = False

Expand Down
10 changes: 10 additions & 0 deletions tests/test_debug.py
Expand Up @@ -6,6 +6,7 @@

from werkzeug.debug import console
from werkzeug.debug import DebuggedApplication
from werkzeug.debug import get_current_traceback
from werkzeug.debug import get_machine_id
from werkzeug.debug.console import HTMLStringO
from werkzeug.debug.repr import debug_repr
Expand Down Expand Up @@ -350,3 +351,12 @@ class MutableException(ValueError):
except MutableException:
# previously crashed: `TypeError: unhashable type 'MutableException'`
Traceback(*sys.exc_info())


def test_exception_without_traceback():
try:
raise Exception("msg1")
except Exception as e:
# filter_hidden_frames should skip this since it has no traceback
e.__context__ = Exception("msg2")
get_current_traceback()

0 comments on commit a026095

Please sign in to comment.