TLDR: this is pdb's post-mortem mode in which jumping is not supposed to work. But it's still very useful.

Painting by Rembrandt (public domain)
I reproduce it with python 3.8.2 as *** Jump failed: can only jump from a 'line' trace event
by running the script "under pdb" like so: python3 -m pdb -c c script.py
and trying to jump to another line in pdb prompt which then appears.
What's happened: an unhandled exception, in this case NameError: name 'b' is not defined
caused python to stop interpreting the script; pdb intercepted this situation and entered its post-mortem mode.
As Almar Klein nicely put it in his blog post,
Post-mortem debugging refers to the concept of entering debug mode after something has broken. There is no setting of breakpoints involved, so it's very quick and you can inspect the full stack trace, making it an effective way of tracing errors.
Although jump
, next
, return
won't work in post-mortem, bt
, up
, down
, ll
and pp
, along with the possibility to import modules and run arbitrary python code directly in the pdb's interactive shell can be very effective ways to get the root cause. In our simple example the root cause of the NameError
is shown immediately upon a quick ll
: pdb prefixes the offending line of code with >>
.
Had we not passed -c c
(meaning continue
), pdb would have shown its prompt and paused before the first line of your program is interpreted, so you'd have a chance to step through the whole program or set a breakpoint before or at the offending line, and jump over it, never entering the post-mortem.
Even in post-mortem, you can prepare a breakpoint anywhere in the program, e.g. break 2
for line 2, and say c
or continue
so pdb will finish post-mortem, reload the file, and restart the program with the updated set of breakpoints.
Another way to deal with it is to import pdb
and pdb.set_trace()
in suspicious code - or since python 3.7, simply breakpoint()
- and run the python program normally (not "under" pdb anymore) which allows then to jump
, next
, return
etc, as well as everything else - when the breakpoint is hit.
If your Python program is started through behave
:
- prefer to run
behave
with --no-capture
whenever using pdb
or similar debuggers (whether post-mortem mode or not), to avoid problems with behave's stdin/stdout capturing making pdb
unresponsive and/or its prompt invisible.
- best of all, if you want to end up in the
pdb
post-mortem mode automatically while potentially still supporting capturing, set the post_mortem
environment variable (can also name it differently) to any value (but only on dev machine, not for automated CI or production!) and commit the following permanently into environment.py
:
def after_step(context, step):
import os
if 'post_mortem' in os.environ and step.status == 'failed':
import pdb
# Similar to "behave --no-capture" calling stop_capture() ensures visibility of pdb's prompts,
# while still supporting capture until an uncaught error occurs.
# Warning: this does rely on behave's internals which might change
context._runner.stop_capture() # pylint: disable=protected-access
pdb.post_mortem(step.exc_traceback)