Bug Report: php-debug adapter spawned but DAP initialize never delivered — Remote-SSH → Dev Containers (Windows client → macOS host → Docker container)
Report to: https://github.com/microsoft/vscode-remote-release/issues (VS Code Remote-SSH + Dev Containers)
Also relevant: https://github.com/xdebug/vscode-php-debug/issues
Summary
PHP (Xdebug) debugging in a Dev Container fails with a 3-hop remote chain:
Windows VS Code (UI) → Remote-SSH → macOS host → Dev Containers → Docker container.
The php-debug adapter process is correctly spawned inside the container with its stdio connected via socketpairs to the container's extension host, but the DAP session never sends initialize to the adapter. The adapter stays idle forever and never binds the Xdebug port (9003), so Xdebug connection attempts fail. The exact same chain works fine for Java debugging (vscode-java-debug), proving the DAP transport channel itself is OK — the failure is specific to this php-debug session.
Driving the php-debug adapter directly (bypassing VS Code) with initialize + launch works perfectly: it binds 127.0.0.1:9003 and logs Listening on { address: '127.0.0.1', family: 'IPv4', port: 9003 }.
Environment
| Component |
Value |
| VS Code client |
Windows, server build 585eba7c0c34fd6b30faac7c62a42050bfbc0086 (v1.108.1) |
| Remote host |
macOS (Docker Desktop) |
| Connection chain |
Windows UI → Remote-SSH → macOS → Dev Containers → container wordpress-wordpress-1 |
| Container OS |
Linux (WordPress official image, PHP 8.3.33 / Apache mod_php) |
| Extension |
xdebug.php-debug 1.40.1 (installed only in container) |
| Xdebug |
3.5.3, mode=debug, start_with_request=yes, client_host=127.0.0.1:9003, xdebug.log=/tmp/xdebug.log |
| Workspace |
/var/www/html (container) ↔ ${workspaceFolder}; Dev Container opened over Remote-SSH |
| Java control case |
Java Debug (vscode-java-debug) in a different Dev Container over the same 3-hop chain → works |
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug (WordPress)",
"type": "php",
"request": "launch",
"port": 9003,
"hostname": "127.0.0.1",
"log": true,
"trace": true,
"pathMappings": {
"/var/www/html": "/var/www/html"
}
}
]
}
Steps to reproduce
- Windows VS Code, connect Remote-SSH to macOS, then "Reopen in Container" for the WordPress dev container (devcontainer.json using compose.yaml + docker-compose.override.yaml, service
wordpress, workspaceFolder /var/www/html, remoteUser root).
- Open any PHP file, set a breakpoint, press F5 with the "Listen for XDebug (WordPress)" config.
- Status bar shows "Listening for Xdebug" (extension's status bar item), but:
- no listener on TCP 9003 inside the container (
/proc/net/tcp, /proc/net/tcp6: nothing on :232B),
- adapter process stays in
S state (idle epoll) forever,
- "PHP Debug" output channel stays empty (no
Listening on … ever printed),
- every web request to the container logs Xdebug
ERR: Could not connect to debugging client. Tried: 127.0.0.1:9003.
Evidence collected inside the container
1. Adapter is spawned by the container extension host and its stdio is a socketpair to the exthost
$ ps -ef | grep phpDebug
1076 478 ... node -e delete process.env.ELECTRON_RUN_AS_NODE;require(process.argv[1]) \
/root/.vscode-server/extensions/xdebug.php-debug-1.40.1/out/phpDebug.js
$ ls -l /proc/1076/fd | grep socket
0 -> socket:[12951007]
1 -> socket:[12951009]
2 -> socket:[12951011]
3 -> socket:[12951013]
$ ls -l /proc/478/fd | grep -E '12951006|12951008|12951010|12951012' # exthost holds the peers
39 -> socket:[12951006]
43 -> socket:[12951008]
45 -> socket:[12951010]
47 -> socket:[12951012]
So: adapter stdio is wired to the container extension host (PID 478) through socketpairs. If the workbench had sent initialize, it would have been relayed.
2. The adapter never receives any DAP message
/proc/1076/stat shows state S (sleeping in epoll), no bind on 9003.
- Container exthost log shows php-debug activated on
onDebugResolve:php and then nothing else:
2026-08-12 02:00:21.095 [info] ExtensionService#_doActivateExtension vscode.debug-server-ready, startup: false, activationEvent: 'onDebugResolve'
2026-08-12 02:00:21.096 [info] ExtensionService#_doActivateExtension xdebug.php-debug, startup: false, activationEvent: 'onDebugResolve:php'
3. Direct DAP drive of the same adapter works perfectly (control experiment)
A minimal Node script spawned phpDebug.js directly inside the container, sent initialize then launch over stdio:
initialize → response OK
launch → Listening on { address: '127.0.0.1', family: 'IPv4', port: 9003 }
/proc/net/tcp then shows 0100007F:232B ... 0A (listening 127.0.0.1:9003)
So the adapter, Xdebug, container network, launch config and pathMappings are all healthy. The failure is in the VS Code debug-session plumbing between the Windows workbench and the adapter over the nested Remote-SSH → Dev Containers connection.
4. Xdebug side is healthy and dialing the right address
Xdebug 3.5.3 in the container; conf.d/zz-wordpress.ini loads last with client_host=127.0.0.1, client_port=9003, mode=debug, start_with_request=yes. /tmp/xdebug.log (mode 666) records every request:
[18] [Step Debug] INFO: Connecting to configured address/port: 127.0.0.1:9003.
[18] [Step Debug] ERR: Could not connect to debugging client. Tried: 127.0.0.1:9003
What we already ruled out
- ❌ Stale/dirty container connection → force-recreated the container (
--force-recreate), fresh reattach, still reproduces.
- ❌ Xdebug config, port collisions, firewall inside container, pathMappings, breakpoint registration, extension activation order.
- ❌
hostname: 127.0.0.1 in launch.json (direct drive used the same value and worked).
- ❌ The adapter itself / a bug in php-debug 1.40.1 logic (direct DAP drive works).
- ✅ The DAP transport over this 3-hop chain is functional in general (Java debugging works in a parallel Dev Container).
Suspected cause
The php-debug DebugSession is created with a non-file workspace URI (vscode-remote://…) inside a Dev Container opened through Remote-SSH. php-debug's resolveDebugConfiguration contains Dev-Container-specific rewriting for folder.uri.scheme !== 'file' (it rewrites pathMappings ${workspaceFolder} → folder.uri.toString()), which is unique among debuggers here and is the only code path that differs from the working Java case. Something in that resolve → session-creation → adapter-spawn handshake over the nested remote connection prevents the workbench from ever sending initialize.
Request
Please investigate why, with Remote-SSH + Dev Containers (3-hop chain), the workbench spawns the php-debug adapter but never sends the DAP initialize request, so the adapter never binds its Xdebug port. Expected: debug session works like plain Remote-SSH (where the same setup is reported working), or at least an actionable error is surfaced.
Attachments / diagnostics that could help
Bug Report: php-debug adapter spawned but DAP
initializenever delivered — Remote-SSH → Dev Containers (Windows client → macOS host → Docker container)Summary
PHP (Xdebug) debugging in a Dev Container fails with a 3-hop remote chain:
Windows VS Code (UI) → Remote-SSH → macOS host → Dev Containers → Docker container.
The php-debug adapter process is correctly spawned inside the container with its stdio connected via socketpairs to the container's extension host, but the DAP session never sends
initializeto the adapter. The adapter stays idle forever and never binds the Xdebug port (9003), so Xdebug connection attempts fail. The exact same chain works fine for Java debugging (vscode-java-debug), proving the DAP transport channel itself is OK — the failure is specific to this php-debug session.Driving the php-debug adapter directly (bypassing VS Code) with
initialize+launchworks perfectly: it binds127.0.0.1:9003and logsListening on { address: '127.0.0.1', family: 'IPv4', port: 9003 }.Environment
585eba7c0c34fd6b30faac7c62a42050bfbc0086(v1.108.1)wordpress-wordpress-1mode=debug,start_with_request=yes,client_host=127.0.0.1:9003,xdebug.log=/tmp/xdebug.log/var/www/html(container) ↔${workspaceFolder}; Dev Container opened over Remote-SSHlaunch.json
{ "version": "0.2.0", "configurations": [ { "name": "Listen for XDebug (WordPress)", "type": "php", "request": "launch", "port": 9003, "hostname": "127.0.0.1", "log": true, "trace": true, "pathMappings": { "/var/www/html": "/var/www/html" } } ] }Steps to reproduce
wordpress, workspaceFolder/var/www/html, remoteUserroot)./proc/net/tcp,/proc/net/tcp6: nothing on:232B),Sstate (idle epoll) forever,Listening on …ever printed),ERR: Could not connect to debugging client. Tried: 127.0.0.1:9003.Evidence collected inside the container
1. Adapter is spawned by the container extension host and its stdio is a socketpair to the exthost
So: adapter stdio is wired to the container extension host (PID 478) through socketpairs. If the workbench had sent
initialize, it would have been relayed.2. The adapter never receives any DAP message
/proc/1076/statshows stateS(sleeping inepoll), no bind on 9003.onDebugResolve:phpand then nothing else:3. Direct DAP drive of the same adapter works perfectly (control experiment)
A minimal Node script spawned
phpDebug.jsdirectly inside the container, sentinitializethenlaunchover stdio:initialize→ response OKlaunch→Listening on { address: '127.0.0.1', family: 'IPv4', port: 9003 }/proc/net/tcpthen shows0100007F:232B ... 0A(listening 127.0.0.1:9003)So the adapter, Xdebug, container network, launch config and pathMappings are all healthy. The failure is in the VS Code debug-session plumbing between the Windows workbench and the adapter over the nested Remote-SSH → Dev Containers connection.
4. Xdebug side is healthy and dialing the right address
Xdebug 3.5.3 in the container;
conf.d/zz-wordpress.iniloads last withclient_host=127.0.0.1,client_port=9003,mode=debug,start_with_request=yes./tmp/xdebug.log(mode 666) records every request:What we already ruled out
--force-recreate), fresh reattach, still reproduces.hostname: 127.0.0.1in launch.json (direct drive used the same value and worked).Suspected cause
The php-debug DebugSession is created with a non-
fileworkspace URI (vscode-remote://…) inside a Dev Container opened through Remote-SSH. php-debug'sresolveDebugConfigurationcontains Dev-Container-specific rewriting forfolder.uri.scheme !== 'file'(it rewritespathMappings${workspaceFolder}→folder.uri.toString()), which is unique among debuggers here and is the only code path that differs from the working Java case. Something in that resolve → session-creation → adapter-spawn handshake over the nested remote connection prevents the workbench from ever sendinginitialize.Request
Please investigate why, with Remote-SSH + Dev Containers (3-hop chain), the workbench spawns the php-debug adapter but never sends the DAP
initializerequest, so the adapter never binds its Xdebug port. Expected: debug session works like plain Remote-SSH (where the same setup is reported working), or at least an actionable error is surfaced.Attachments / diagnostics that could help
vscode-remote-releasedocs on reporting: https://code.visualstudio.com/docs/remote/troubleshooting--log verboseon the client:%APPDATA%\Code\logs\<session>\window...\exthost\remoteagent.logand the container-sideremoteexthost.log.