Error when debugging workflow using vscode python debugger

Actual Behavior

When hitting a breakpoint in a workflow, the debugger freezes with the following symptoms:

  1. Infinite loader in “local variables section”
    image
  2. All debug actions stop working (Step over / Continue etc.)
  3. The following stack trace is printed:
Traceback (most recent call last):
  File "/Users/user/.vscode/extensions/ms-python.debugpy-2024.5.11001011-darwin-arm64/bundled/libs/debugpy/_vendored/pydevd/pydevd.py", line 1783, in process_internal_commands
    int_cmd.do_it(self)
  File "/Users/user/.vscode/extensions/ms-python.debugpy-2024.5.11001011-darwin-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 528, in do_it
    self.method(dbg, *self.args, **self.kwargs)
  File "/Users/user/.vscode/extensions/ms-python.debugpy-2024.5.11001011-darwin-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py", line 489, in new_func
    with filter_all_warnings():
  File "/Users/user/.pyenv/versions/3.10.12/lib/python3.10/contextlib.py", line 135, in __enter__
    return next(self.gen)
  File "/Users/user/.vscode/extensions/ms-python.debugpy-2024.5.11001011-darwin-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py", line 480, in filter_all_warnings
    with warnings.catch_warnings():
  File "/Users/user/.pyenv/versions/3.10.12/lib/python3.10/warnings.py", line 446, in __init__
    self._module = sys.modules['warnings'] if module is None else module
  File "/Users/user/project/.venv/lib/python3.10/site-packages/temporalio/worker/workflow_sandbox/_importer.py", line 393, in __getitem__
    return self.current[key]
KeyError: 'warnings'

I assume the problem and resolution has something to do with the sandbox, and the “warnings” module which seems to be required by the debugpy extension.
If you have any recommended solutions that would be appreciated.
Thank you!

Steps to reproduce:

  1. Use vscode, python debugger extension. Both latest versions.
  2. Use the attached launch configuration
  3. Place breakpoint on “return x” in the workflow
  4. Run the workflow.

Code

"""example_workflow.py"""

from temporalio import workflow

@workflow.defn
class ExampleWorkflow:
    @workflow.run
    async def run(self, x: str) -> str:
        return x

"""run_worker.py"""

import asyncio
from temporalio.client import Client
from temporalio.worker import Worker

from example_workflow import ExampleWorkflow


async def main():
    client = await Client.connect("localhost:7233", namespace="example_namespace")

    worker = Worker(
        client,
        task_queue="my-queue",
        workflows=[ExampleWorkflow],
        debug_mode=True,
    )
    await worker.run()


if __name__ == "__main__":
    asyncio.run(main())

Launch configuration

       {
            "name": "Python",
            "type": "debugpy",
            "request": "launch",
            "program": "${workspaceFolder}/run_worker.py", 
            "console": "integratedTerminal",
            "cwd": "${workspaceFolder}",
            "args": [],
            "stopOnEntry": false,
            "justMyCode": false,
        }

See this issue. Usually you’ll only want to debug workflow replays not live workflows since live workflows are dependent on time and can timeout on breakpoint. See documentation on using a replayer.

When running via a replayer, you’ll want to set debug_mode=True to disable the deadlock detector. Also, the sandbox has issues with the vscode debugger, so you’ll need to disable sandbox (see previously-linked issue or Python SDK README for how to disable the sandbox when creating the replayer).