Opened 10 years ago

Closed 9 years ago

#23643 closed New feature (fixed)

Have debug page show "During handling of this exception, another exception occurred.."

Reported by: Ram Rachum Owned by: Tomáš Ehrlich
Component: Core (Other) Version: dev
Severity: Release blocker Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Python 3 has this thing where exceptions have optional __cause__ and __context__, which is useful when an exception causes another exception. When you get a Python 3 traceback, you see tracebacks for all the exceptions in the tree. Currently it seems that the Django debug page ignores this information. It would be nice if it would display a separate traceback for each such exception.

Change History (15)

comment:1 by Baptiste Mispelon, 10 years ago

Triage Stage: UnreviewedAccepted

I like this idea.

I find that it really helps with debugging (especially when Django has a bad habit of masking exceptions).

comment:2 by Tomáš Ehrlich, 10 years ago

Owner: changed from nobody to Tomáš Ehrlich
Status: newassigned
Version: 1.7master

comment:3 by Tomáš Ehrlich, 10 years ago

Has patch: set

comment:4 by Tomáš Ehrlich, 10 years ago

The easiest way to review, hook up this view into your urlconf:

def chained_exception(request):
    try:
        raise AttributeError('Top level')
    except AttributeError as explicit:
        try:
            raise ValueError('Second exception') from explicit
        except ValueError:
            raise IndexError('Final exception')

comment:5 by Tim Graham, 10 years ago

Component: Python 3Core (Other)

comment:6 by Tim Graham <timograham@…>, 10 years ago

Resolution: fixed
Status: assignedclosed

In 8414fcf1:

Fixes #23643 -- Added chained exception details to debug view.

comment:7 by Tim Graham, 10 years ago

Has patch: unset
Resolution: fixed
Severity: NormalRelease blocker
Status: closednew

Ran into a crash (Python 2 only) when a view raised an IntegrityError:

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "/home/tim/code/django/django/contrib/staticfiles/handlers.py", line 63, in __call__
    return self.application(environ, start_response)
  File "/home/tim/code/django/django/core/handlers/wsgi.py", line 177, in __call__
    response = self.get_response(request)
  File "/home/tim/code/django/django/core/handlers/base.py", line 218, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/home/tim/code/django/django/core/handlers/base.py", line 261, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/home/tim/code/django/django/views/debug.py", line 97, in technical_500_response
    html = reporter.get_traceback_html()
  File "/home/tim/code/django/django/views/debug.py", line 387, in get_traceback_html
    c = Context(self.get_traceback_data(), use_l10n=False)
  File "/home/tim/code/django/django/views/debug.py", line 332, in get_traceback_data
    frames = self.get_traceback_frames()
  File "/home/tim/code/django/django/views/debug.py", line 503, in get_traceback_frames
    tb = self.tb if not exceptions else exc_value.__traceback__
AttributeError: 'IntegrityError' object has no attribute '__traceback__'

comment:8 by Tomáš Ehrlich, 10 years ago

Has patch: set
Status: newassigned
  1. I've submitted new PR with updated plain-text output https://github.com/django/django/pull/4412
  1. I couldn't reproduce the AttributeError. I tried this simple view:
def view(request):
    raise IntegrityError('Error raised')

We could simple replace this line:

      tb = self.tb if not exceptions else exc_value.__traceback__

with safer, but longer:

        if not exceptions or not hasattr(exc_value, '__traceback__'):
            tb = self.tb
        else:
            tb = exc_value.__traceback__

The point was that exceptions should have been already empty in Python 2, but somewhat it wasn't. Would be great if we could reproduce your problem.

comment:9 by Tim Graham, 10 years ago

Patch needs improvement: set

Here's a view to reproduce AttributeError: 'IntegrityError' object has no attribute '__traceback__':

def vote(request, poll_id):
    Question.objects.create(question_text='foobar')

comment:10 by Florian Apolloner, 10 years ago

See the PR https://github.com/django/django/pull/4530 for more details.

comment:11 by fero, 10 years ago

And the PR https://github.com/django/django/pull/4568

the cause attribute is set in db/utils.py in wrapping DatabaseException

Version 0, edited 10 years ago by fero (next)

comment:12 by Tim Graham <timograham@…>, 9 years ago

In 38eacbd:

Refs #23643 -- Fixed debug view regression on Python 2.

Thanks Tomáš Ehrlich for help with the patch.

comment:13 by Tim Graham, 9 years ago

Needs tests: set
Patch needs improvement: unset

The one item remaining is adding a test for the plain text exception chain report. Tomas said he will do that soon.

comment:14 by Tomáš Ehrlich, 9 years ago

Needs tests: unset

Tests added, thank you for patience!

comment:15 by Tim Graham, 9 years ago

Resolution: fixed
Status: assignedclosed

In 59383f1e3a8ab5a6477dbd5bb1d7c32366a9d8f8:

Ref #23643 -- Added plain text report of exception chain.

Note: See TracTickets for help on using tickets.
Back to Top