From 26a54bc2abaf9fe3ada4c6ea40fa96a038508eb4 Mon Sep 17 00:00:00 2001 From: Philip DePetro Date: Tue, 12 May 2026 12:27:14 -0700 Subject: [PATCH 1/2] Prevent invalid scopes request from crashing debug session If an unmapped or non-numeric frameId is sent in a scopes request, int() raises a ValueError that terminates the debug session. Wrap the scope construction in a try/except so that invalid frameIds return an empty scopes list instead, which is valid per the DAP spec. --- .../pydevd_process_net_command_json.py | 11 ++++--- .../test_pydevd_process_net_command_json.py | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/debugpy/_vendored/pydevd/tests_python/test_pydevd_process_net_command_json.py diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py index 0c483af4..163ef599 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py @@ -1109,10 +1109,13 @@ def on_scopes_request(self, py_db, request): frame_id = request.arguments.frameId variables_reference = frame_id - scopes = [ - Scope("Locals", ScopeRequest(int(variables_reference), "locals"), False, presentationHint="locals"), - Scope("Globals", ScopeRequest(int(variables_reference), "globals"), False), - ] + try: + scopes = [ + Scope("Locals", ScopeRequest(int(variables_reference), "locals"), False, presentationHint="locals"), + Scope("Globals", ScopeRequest(int(variables_reference), "globals"), False), + ] + except Exception: + scopes = [] body = ScopesResponseBody(scopes) scopes_response = pydevd_base_schema.build_response(request, kwargs={"body": body}) return NetCommand(CMD_RETURN, 0, scopes_response, is_json=True) diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_pydevd_process_net_command_json.py b/src/debugpy/_vendored/pydevd/tests_python/test_pydevd_process_net_command_json.py new file mode 100644 index 00000000..7e746cda --- /dev/null +++ b/src/debugpy/_vendored/pydevd/tests_python/test_pydevd_process_net_command_json.py @@ -0,0 +1,32 @@ +def test_on_scopes_request_with_valid_frame_id(): + from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema + from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor + + processor = PyDevJsonCommandProcessor(pydevd_base_schema.from_json) + request = pydevd_schema.ScopesRequest(pydevd_schema.ScopesArguments(frameId=1)) + + result = processor.on_scopes_request(None, request) + response = result.as_dict + + assert response["success"] is True + scopes = response["body"]["scopes"] + assert len(scopes) == 2 + assert scopes[0]["name"] == "Locals" + assert scopes[0]["presentationHint"] == "locals" + assert scopes[1]["name"] == "Globals" + + +def test_on_scopes_request_with_invalid_frame_id(): + from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema + from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor + + processor = PyDevJsonCommandProcessor(pydevd_base_schema.from_json) + request = pydevd_schema.ScopesRequest( + pydevd_schema.ScopesArguments(frameId="not_a_number") + ) + + result = processor.on_scopes_request(None, request) + response = result.as_dict + + assert response["success"] is True + assert response["body"]["scopes"] == [] From 811da01565d21e7b3122e6c2a77cc8c4a6749cd6 Mon Sep 17 00:00:00 2001 From: Philip DePetro Date: Tue, 12 May 2026 16:12:19 -0700 Subject: [PATCH 2/2] Add logging for invalid scopes requests Log expected errors (ValueError, TypeError) at info level and unexpected exceptions with full traceback via pydev_log.exception. --- .../pydevd/_pydevd_bundle/pydevd_process_net_command_json.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py index 163ef599..5aaf96d3 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py @@ -1114,7 +1114,11 @@ def on_scopes_request(self, py_db, request): Scope("Locals", ScopeRequest(int(variables_reference), "locals"), False, presentationHint="locals"), Scope("Globals", ScopeRequest(int(variables_reference), "globals"), False), ] + except (ValueError, TypeError): + pydev_log.info("Failed to create scopes for frame id: %s", frame_id) + scopes = [] except Exception: + pydev_log.exception("Failed to create scopes for frame id: %s", frame_id) scopes = [] body = ScopesResponseBody(scopes) scopes_response = pydevd_base_schema.build_response(request, kwargs={"body": body})