You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Before creating a new issue, please check the FAQ to see if your question is answered there.
Environment data
debugpy version: 1.8.20
OS and version: macOS Tahoe
Python version (& distribution if applicable, e.g. Anaconda): 3.13.5
Using VS Code or Visual Studio: VSCode
Actual behavior
In a Jupyter Notebook I have:
%load_ext autoreload
%autoreload 2
The notebook imports another module, let's say import util.
I set a breakpoint in util.py and launch the debugger from a cell calling some function util.fun. So far so good.
Now, after the debugging session ends, I do some changes in util.py, say rename util.fun to util.fun2. If I then launch the debugger from a cell calling util.fun2, debugpy doesn't stop at the breakpoint anymore.
In my example I was renaming a function, but this happens after other, more innocent looking, changes too.
Calling importlib.reload(util) fixes the issue. OTOH removing and readding the breakpoints has no effect at all.
I'm pretty sure this is because the kernel isn't reloading the lib. It's not the debugger, it's jupyter itself (which is why importlib.reload(util) makes it work).
I don't think this is something that debugpy would fix. It's more like the jupyter extension in VS code.
But the behavior of autoreload is different to that of reload by design. Autoreload doesn't reload the module but just replaces the bytecode in changed objects, AFAIK. I fail to see how this has to do with the kernel. The behavior itself is correctly updated, the only thing failing is that breakpoints are missed.
Yeah if I restart the kernel it works. So auto reload is basically breaking the debugger's lookup of the module. I can verify by adding this code to the function.
deffun4():
print("Inside of fun4")
importinspectframe=inspect.currentframe()
print(frame.f_code.co_filename)
With a restart, it prints this:
Inside of fun4
[c:\Users\rchiodo\source\repos\pylance-release\testing\single\src\util.py](file:///C:/Users/rchiodo/source/repos/pylance-release/testing/single/src/util.py)
With autoreload it prints this:
Inside of fun4
<string>
The debugger can't map to the breakpoint, so the breakpoint doesn't bind.
Activity
rchiodo commentedon Mar 3, 2026
I'm pretty sure this is because the kernel isn't reloading the lib. It's not the debugger, it's jupyter itself (which is why importlib.reload(util) makes it work).
I don't think this is something that debugpy would fix. It's more like the jupyter extension in VS code.
memeplex commentedon Mar 3, 2026
But the behavior of autoreload is different to that of reload by design. Autoreload doesn't reload the module but just replaces the bytecode in changed objects, AFAIK. I fail to see how this has to do with the kernel. The behavior itself is correctly updated, the only thing failing is that breakpoints are missed.
rchiodo commentedon Mar 3, 2026
I believe that would be incompatible with how the debugger finds the breakpoints then. The module wouldn't match.
rchiodo commentedon Mar 3, 2026
Yeah if I restart the kernel it works. So auto reload is basically breaking the debugger's lookup of the module. I can verify by adding this code to the function.
With a restart, it prints this:
With autoreload it prints this:
The debugger can't map to the breakpoint, so the breakpoint doesn't bind.
memeplex commentedon Mar 3, 2026
Is there any way to invalidate the debugger lookup table so that it behaves as if the file was just loaded?
rchiodo commentedon Mar 3, 2026
Not change the co_filename on the generated code. It's how the debugger maps the breakpoint.