PTVS
PTVS copied to clipboard
Remote debug attach does not support path mapping
Following the directions here: https://docs.microsoft.com/en-us/visualstudio/python/debugging-python-code-on-remote-linux-machines?view=vs-2019
I cannot get breakpoints to bind.
Internally debugpy is returning this:
1> [DebugAdapter] <-- R (setBreakpoints-12) [20 ms]: {"type":"response","request_seq":12,"success":true,"command":"setBreakpoints","body":{"breakpoints":[{"verified":false,"message":"Breakpoint in file that does not exist.","source":{"path":"c:\\Users\\aku91\\source\\repos\\PythonApplication3\\PythonApplication3\\test.py","sources":[],"checksums":[]},"line":7}]},"seq":15}
This really means we need path mapping for the remote machine. There was some discussion in the past of VSCodeDebugAdapterHost supporting a launch.json that could provide that mapping. Short of that, we'd have to provide that here:
https://github.com/microsoft/PTVS/blob/984cd41766ea27a9b6ac304b437031e7d880899d/Python/Product/PythonTools/PythonTools/Debugger/DebugAdapter/DebugAdapterLauncher.cs#L167
We need to pass the attach request the path mappings like VS code does:
Note: this repros in D16 too.
Need to involve PM as there is potentially a UI component involved. @savannahostrowski
To be specific, we need to decide what the appropriate UX for defining path mappings is. In VSCode, this is done by editing launch.json directly. We could expose it in a similar manner here (which would also have a benefit of giving users access to the complete panoply of debugpy configuration knobs).
However, traditionally, PTVS used GUI dialogs to configure such things. If we do that, it should probably go into the Debugging tab in project properties, and we need to figure out how that UI will look. It's basically a list of entries, each mapping one local absolute path to one remote path; so the UI needs to provide some way to specify project-relative paths there, that would then be automatically expanded before they're handed over to debugpy (debugpy itself can't do this because it doesn't know anything about VS projects).
@ijoosong
This worked before we moved to debugpy, so this should be treated as a regression since we can't support remote debugging without the ability to modify the json that is passed to the debug adapter. We probably need a generic way to do this. Pavel mentioned that the C++ team did some work around this, so we might be able to re-use what they did. Needs PM involvement here to decide what the best path is. /cc @cwebster-99
C++ has something called launch.vs.json, which is roughly equivalent to launch.json in VSCode: https://learn.microsoft.com/en-us/cpp/build/launch-vs-schema-reference-cpp?view=msvc-170
And we actually have a separate issue asking for it to be supported for Python: https://github.com/microsoft/PTVS/issues/7269
If we do that, it would provide a way to specify path mappings, although we might still want a UI long-term.
If we are able to re-use some of the work done by the C++ team to support launch.vs.json
, I think that is a good approach (at least to begin with). We can do more investigation, if there is a need, for a GUI long-term solution. I infer users may be familiar with this approach if they are C++ users or even VS Code users familiar with launch.json
I doubt we'd be able to reuse the actual code, since C++ project system is very different from ours. But we can reuse their spec (i.e. where to look for the file and how to combine it with project settings), and to some extent probably the documentation.
Since launch.vs.json
would do more than just fix this issue, I think it would be best to track it separately - #7434
Hi, I seem to be having a similar issue.
My host is running on MacOS 13.3 with Visual Code Studio 1.81.1 The app I'm working on is a Dockerized Stackstorm installation. Using the devcontainers extension from https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers, version v0.304.0 The debugger is being attached to a remote container whose hostname is "st2sensorcontainer". Debugpy is running and the listen() instruction is being called in the code of this file: ./packages/stackstorm/src/stackstorm/events/dispatch/server/app.py
import multiprocessing
if multiprocessing.current_process().pid > 1:
import debugpy
debugpy.listen(("0.0.0.0", 5678))
print("Debugger is ready to be attached, press F5", flush=True)
debugpy.wait_for_client()
print("Visual Studio Code debugger is now attached", flush=True)
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Attach to sensor",
"type": "python",
"request": "attach",
"logToFile": true,
"connect": {
"host": "st2sensorcontainer",
"port": 5678
},
"clientOS": "Unix",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/opt/project/"
}
]
},
]
}
This issue I am having is that I can't place breakpoints in the debugger as it says "Breakpoint in file that does not exist".
If I hover over a file in the IDE, such as app.py, I get this path (which is the path in the devcontainer): /opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py
However, since the debugger attaches to the remote container st2sensorcontainer, I went to look up that path. In ST2 Python packages are setup in a virtualenv. So the path of that file inside st2sensorcontainer is: /opt/stackstorm/virtualenvs/gcx/lib/python3.8/site-packages/stackstorm/events/dispatch/server/app.py
I've tried to tweak the pathMappings in all different ways. I've tried setting remoteRoot to ".", to "/opt/project", "/opt/project/packages/stackstorm/src/stackstorm", and "/opt/stackstorm/virtualenvs/gcx/lib/python3.8/site-packages/stackstorm". No luck.
I'd appreciate your help. Here is the log:
0 Starting Session:
{
"name": "Python: Attach to sensor",
"type": "python",
"request": "attach",
"logToFile": true,
"connect": {
"host": "st2sensorcontainer",
"port": 5678
},
"clientOS": "Unix",
"pathMappings": [
{
"localRoot": "/opt/project",
"remoteRoot": "/opt/project/"
}
],
"__configurationTarget": 6,
"debugOptions": [
"RedirectOutput",
"ShowReturnValue"
],
"justMyCode": true,
"showReturnValue": true,
"workspaceFolder": "/opt/project"
}
5 Client <-- Adapter:
{
"seq": 1,
"type": "event",
"event": "output",
"body": {
"category": "telemetry",
"output": "ptvsd",
"data": {
"packageVersion": "1.6.7.post1"
}
}
}
5 Client <-- Adapter:
{
"seq": 2,
"type": "event",
"event": "output",
"body": {
"category": "telemetry",
"output": "debugpy",
"data": {
"packageVersion": "1.6.7.post1"
}
}
}
52 Client --> Adapter:
{
"command": "initialize",
"arguments": {
"clientID": "vscode",
"clientName": "Visual Studio Code",
"adapterID": "python",
"pathFormat": "path",
"linesStartAt1": true,
"columnsStartAt1": true,
"supportsVariableType": true,
"supportsVariablePaging": true,
"supportsRunInTerminalRequest": true,
"locale": "en",
"supportsProgressReporting": true,
"supportsInvalidatedEvent": true,
"supportsMemoryReferences": true,
"supportsArgsCanBeInterpretedByShell": true,
"supportsMemoryEvent": true,
"supportsStartDebuggingRequest": true
},
"type": "request",
"seq": 1
}
54 Client <-- Adapter:
{
"seq": 3,
"type": "response",
"request_seq": 1,
"success": true,
"command": "initialize",
"body": {
"supportsCompletionsRequest": true,
"supportsConditionalBreakpoints": true,
"supportsConfigurationDoneRequest": true,
"supportsDebuggerProperties": true,
"supportsDelayedStackTraceLoading": true,
"supportsEvaluateForHovers": true,
"supportsExceptionInfoRequest": true,
"supportsExceptionOptions": true,
"supportsFunctionBreakpoints": true,
"supportsHitConditionalBreakpoints": true,
"supportsLogPoints": true,
"supportsModulesRequest": true,
"supportsSetExpression": true,
"supportsSetVariable": true,
"supportsValueFormattingOptions": true,
"supportsTerminateRequest": true,
"supportsGotoTargetsRequest": true,
"supportsClipboardContext": true,
"exceptionBreakpointFilters": [
{
"filter": "raised",
"label": "Raised Exceptions",
"default": false,
"description": "Break whenever any exception is raised."
},
{
"filter": "uncaught",
"label": "Uncaught Exceptions",
"default": true,
"description": "Break when the process is exiting due to unhandled exception."
},
{
"filter": "userUnhandled",
"label": "User Uncaught Exceptions",
"default": false,
"description": "Break when exception escapes into library code."
}
],
"supportsStepInTargetsRequest": true
}
}
61 Client --> Adapter:
{
"command": "attach",
"arguments": {
"name": "Python: Attach to sensor",
"type": "python",
"request": "attach",
"logToFile": true,
"connect": {
"host": "st2sensorcontainer",
"port": 5678
},
"clientOS": "Unix",
"pathMappings": [
{
"localRoot": "/opt/project",
"remoteRoot": "/opt/project/"
}
],
"__configurationTarget": 6,
"debugOptions": [
"RedirectOutput",
"ShowReturnValue"
],
"justMyCode": true,
"showReturnValue": true,
"workspaceFolder": "/opt/project",
"__sessionId": "bc908d13-9507-44bf-b310-4b57df81b90f"
},
"type": "request",
"seq": 2
}
62 Client <-- Adapter:
{
"seq": 4,
"type": "event",
"event": "debugpyWaitingForServer",
"body": {
"host": "127.0.0.1",
"port": 60177
}
}
117 Client <-- Adapter:
{
"seq": 5,
"type": "event",
"event": "initialized"
}
125 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "__init__.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/__init__.py"
},
"lines": [
17
],
"breakpoints": [
{
"line": 17
}
],
"sourceModified": false
},
"type": "request",
"seq": 3
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"lines": [
117
],
"breakpoints": [
{
"line": 117
}
],
"sourceModified": false
},
"type": "request",
"seq": 4
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "client.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/client/client.py"
},
"lines": [
69
],
"breakpoints": [
{
"line": 69
}
],
"sourceModified": false
},
"type": "request",
"seq": 5
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "continuation.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/models/continuation.py"
},
"lines": [
148
],
"breakpoints": [
{
"line": 148
}
],
"sourceModified": false
},
"type": "request",
"seq": 6
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "debugger.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/debugger.py"
},
"lines": [
11
],
"breakpoints": [
{
"line": 11
}
],
"sourceModified": false
},
"type": "request",
"seq": 7
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "handler_result_action.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/actions/handler_result_action.py"
},
"lines": [
37
],
"breakpoints": [
{
"line": 37
}
],
"sourceModified": false
},
"type": "request",
"seq": 8
}
126 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "sandbox.py",
"path": "/opt/project/packages/stackstorm/sandbox.py"
},
"lines": [
94,
237
],
"breakpoints": [
{
"line": 94
},
{
"line": 237
}
],
"sourceModified": false
},
"type": "request",
"seq": 9
}
127 Client --> Adapter:
{
"command": "setFunctionBreakpoints",
"arguments": {
"breakpoints": []
},
"type": "request",
"seq": 10
}
127 Client --> Adapter:
{
"command": "setExceptionBreakpoints",
"arguments": {
"filters": [
"uncaught"
]
},
"type": "request",
"seq": 11
}
130 Client <-- Adapter:
{
"seq": 6,
"type": "response",
"request_seq": 3,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 200,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "__init__.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/__init__.py"
},
"line": 17
}
]
}
}
174 Client <-- Adapter:
{
"seq": 7,
"type": "response",
"request_seq": 4,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 201,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"line": 117
}
]
}
}
176 Client <-- Adapter:
{
"seq": 8,
"type": "response",
"request_seq": 5,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 202,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "client.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/client/client.py"
},
"line": 69
}
]
}
}
179 Client <-- Adapter:
{
"seq": 9,
"type": "response",
"request_seq": 6,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 203,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "continuation.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/models/continuation.py"
},
"line": 148
}
]
}
}
222 Client <-- Adapter:
{
"seq": 10,
"type": "response",
"request_seq": 7,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 204,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "debugger.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/debugger.py"
},
"line": 11
}
]
}
}
225 Client <-- Adapter:
{
"seq": 11,
"type": "response",
"request_seq": 8,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 205,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "handler_result_action.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/actions/handler_result_action.py"
},
"line": 37
}
]
}
}
231 Client <-- Adapter:
{
"seq": 12,
"type": "response",
"request_seq": 9,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 206,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "sandbox.py",
"path": "/opt/project/packages/stackstorm/sandbox.py"
},
"line": 94
},
{
"verified": false,
"id": 207,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "sandbox.py",
"path": "/opt/project/packages/stackstorm/sandbox.py"
},
"line": 237
}
]
}
}
274 Client <-- Adapter:
{
"seq": 13,
"type": "response",
"request_seq": 10,
"success": true,
"command": "setFunctionBreakpoints",
"body": {
"breakpoints": []
}
}
277 Client <-- Adapter:
{
"seq": 14,
"type": "response",
"request_seq": 11,
"success": true,
"command": "setExceptionBreakpoints"
}
301 Client --> Adapter:
{
"command": "configurationDone",
"type": "request",
"seq": 12
}
312 Client <-- Adapter:
{
"seq": 15,
"type": "response",
"request_seq": 12,
"success": true,
"command": "configurationDone"
}
325 Client --> Adapter:
{
"command": "threads",
"type": "request",
"seq": 13
}
326 Client <-- Adapter:
{
"seq": 16,
"type": "response",
"request_seq": 2,
"success": true,
"command": "attach"
}
326 Client <-- Adapter:
{
"seq": 17,
"type": "event",
"event": "process",
"body": {
"name": "/opt/stackstorm/st2/lib/python3.8/site-packages/st2reactor/container/sensor_wrapper.py",
"systemProcessId": 9,
"isLocalProcess": true,
"startMethod": "attach"
}
}
326 Client <-- Adapter:
{
"seq": 18,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 1
}
}
326 Client <-- Adapter:
{
"seq": 19,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 2
}
}
326 Client <-- Adapter:
{
"seq": 20,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 3
}
}
326 Client <-- Adapter:
{
"seq": 21,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 4
}
}
326 Client <-- Adapter:
{
"seq": 22,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 5
}
}
326 Client <-- Adapter:
{
"seq": 23,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 6
}
}
327 Client <-- Adapter:
{
"seq": 24,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 7
}
}
327 Client <-- Adapter:
{
"seq": 25,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 9
}
}
327 Client <-- Adapter:
{
"seq": 26,
"type": "event",
"event": "thread",
"body": {
"reason": "started",
"threadId": 8
}
}
372 Client <-- Adapter:
{
"seq": 27,
"type": "response",
"request_seq": 13,
"success": true,
"command": "threads",
"body": {
"threads": [
{
"id": 1,
"name": "MainThread"
},
{
"id": 2,
"name": "pymongo_server_monitor_thread"
},
{
"id": 3,
"name": "pymongo_kill_cursors_thread"
},
{
"id": 4,
"name": "pymongo_server_rtt_thread"
},
{
"id": 5,
"name": "Thread-6"
},
{
"id": 6,
"name": "ThreadPoolExecutor-0_0"
},
{
"id": 7,
"name": "pymongo_server_monitor_thread"
},
{
"id": 9,
"name": "pymongo_kill_cursors_thread"
},
{
"id": 8,
"name": "pymongo_server_rtt_thread"
}
]
}
}
472 Client --> Adapter:
{
"command": "threads",
"type": "request",
"seq": 14
}
475 Client <-- Adapter:
{
"seq": 28,
"type": "response",
"request_seq": 14,
"success": true,
"command": "threads",
"body": {
"threads": [
{
"id": 1,
"name": "MainThread"
},
{
"id": 2,
"name": "pymongo_server_monitor_thread"
},
{
"id": 3,
"name": "pymongo_kill_cursors_thread"
},
{
"id": 4,
"name": "pymongo_server_rtt_thread"
},
{
"id": 5,
"name": "Thread-6"
},
{
"id": 6,
"name": "ThreadPoolExecutor-0_0"
},
{
"id": 7,
"name": "pymongo_server_monitor_thread"
},
{
"id": 9,
"name": "pymongo_kill_cursors_thread"
},
{
"id": 8,
"name": "pymongo_server_rtt_thread"
}
]
}
}
17107 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"lines": [
53,
117
],
"breakpoints": [
{
"line": 53
},
{
"line": 117
}
],
"sourceModified": false
},
"type": "request",
"seq": 15
}
17113 Client <-- Adapter:
{
"seq": 29,
"type": "response",
"request_seq": 15,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 208,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"line": 53
},
{
"verified": false,
"id": 209,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"line": 117
}
]
}
}
17785 Client --> Adapter:
{
"command": "setBreakpoints",
"arguments": {
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"lines": [
117
],
"breakpoints": [
{
"line": 117
}
],
"sourceModified": false
},
"type": "request",
"seq": 16
}
17789 Client <-- Adapter:
{
"seq": 30,
"type": "response",
"request_seq": 16,
"success": true,
"command": "setBreakpoints",
"body": {
"breakpoints": [
{
"verified": false,
"id": 210,
"message": "Breakpoint in file that does not exist.",
"source": {
"name": "app.py",
"path": "/opt/project/packages/stackstorm/src/stackstorm/events/dispatch/server/app.py"
},
"line": 117
}
]
}
}
Well.. I found the issue.
The localRoot should be the path in the devcontainer, and the remoteRoot the path in the remote container (our st2sensorcontainer in this case).
AND there was actually another issue. In this case I had to add the following to my configuration (as by default it is set to true): "justMyCode": false,