Why does Xdebug 3 use port 9003, and which settings replaced Xdebug 2's xdebug.remote_* step-debugging options?
answer
- old default 9000 clashed with PHP-FPM
- remote_enable became mode=debug
- remote_autostart became start_with_request=yes
- remote_connect_back became discover_client_host
- remote_host/port became client_host/port
basics
~10 sXdebug 3 moved the default debug port from 9000, which PHP-FPM also listens on by default, to 9003, and replaced remote_enable with mode=debug, remote_host/remote_port with client_host/client_port, remote_autostart with start_with_request=yes and remote_connect_back with discover_client_host.
solid answer
~40 sXdebug 2 connected to port 9000 by default, which is also PHP-FPM's default `listen = 127.0.0.1:9000`. A debugger pointed there can reach FPM instead of the IDE, and Xdebug 3 changed the default to **9003**. Xdebug 3 also replaced the feature flags with one `xdebug.mode`: `remote_enable=1` becomes `mode=debug`, `remote_autostart=1` becomes `start_with_request=yes`, `remote_mode=req` is the default `trigger` behaviour, and `remote_mode=jit` becomes `start_upon_error=yes`. The connection settings were renamed: `remote_host` to `client_host`, `remote_port` to `client_port`, `remote_connect_back` to `discover_client_host`, `remote_timeout` to `connect_timeout_ms`, `remote_log` to `log`. On the CLI, `XDEBUG_CONFIG=idekey=...` gave way to `XDEBUG_SESSION`. Old `remote_*` lines have no effect in Xdebug 3; it only flags them as renamed in its diagnostics, which is why copied Xdebug 2 configs appear to fail silently.
code
ini · 11 lines; Xdebug 2 (no effect in Xdebug 3)
;xdebug.remote_enable=1
;xdebug.remote_autostart=1
;xdebug.remote_host=192.168.56.1
;xdebug.remote_port=9000
; Xdebug 3 equivalent
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=192.168.56.1
xdebug.client_port=9003go deeper
Recall that Xdebug 3 uses port 9003 and xdebug.mode=debug, and that remote_* settings are from Xdebug 2.
Map each remote_* setting to its Xdebug 3 replacement and explain why 9000 was a poor default next to PHP-FPM.
Show you can audit inherited images and configs for dead Xdebug 2 settings and verify the effective values with xdebug_info().
Own a single, versioned Xdebug config in the team's base images so outdated tutorials cannot drift into it.
## Why this question comes up Xdebug 3, released in late 2020, reorganised the configuration completely. Years of blog posts, Docker images and team wikis still show Xdebug 2 settings. A developer who copies them into an Xdebug 3 setup gets **no debugging and no obvious error**: the old settings have no effect, and Xdebug 3 only reports them as renamed or removed in its diagnostics (a critical entry shown by `xdebug_info()` and written to PHP's error log, when `E_DEPRECATED` is part of `error_reporting`). Knowing the mapping is the fastest way to fix such a setup. ## The port change | | Xdebug 2 | Xdebug 3 | |---|---|---| | Default debug port | 9000 | **9003** | | Setting name | `xdebug.remote_port` | `xdebug.client_port` | Port 9000 is also where PHP-FPM listens by default (`listen = 127.0.0.1:9000` in the shipped pool configuration). On a machine that runs both, a debugger aimed at 9000 can end up talking to FPM instead of the IDE. Xdebug documents this as a session-initialisation failure (`DBG-E-SES-INIT`) whose remedy is to keep FPM and the debugger on different ports. The IDE must listen on the same port Xdebug dials; current IDEs default to 9003, so the simplest fix is to leave `client_port` alone. ## From feature flags to modes Xdebug 2 had one switch per feature (`remote_enable`, `profiler_enable`, `auto_trace`, `coverage_enable`, `default_enable`). Xdebug 3 replaced them all with **`xdebug.mode`**, a comma-separated list such as `debug` or `develop,debug`. For step debugging: - `xdebug.remote_enable=1` becomes `xdebug.mode=debug`. - `xdebug.remote_autostart=1` becomes `xdebug.start_with_request=yes`. - `xdebug.remote_mode=req` (the old default) becomes `xdebug.start_with_request=trigger`, which is already the default for debug mode. - `xdebug.remote_mode=jit` becomes `xdebug.start_upon_error=yes`. ## Renamed connection settings | Xdebug 2 | Xdebug 3 | |---|---| | `xdebug.remote_host` | `xdebug.client_host` | | `xdebug.remote_port` (9000) | `xdebug.client_port` (9003) | | `xdebug.remote_connect_back` | `xdebug.discover_client_host` | | `xdebug.remote_addr_header` | `xdebug.client_discovery_header` | | `xdebug.remote_timeout` | `xdebug.connect_timeout_ms` | | `xdebug.remote_log` | `xdebug.log`, which also covers other features | | `xdebug.remote_log_level` | `xdebug.log_level` | | `xdebug.remote_handler` | removed; DBGp is the only protocol | `xdebug.idekey` kept its name. It is only really needed when a **DBGp proxy** routes sessions for several developers. Its default comes from the `DBGP_IDEKEY` environment variable, or is empty. ## Behaviour changes that look like bugs 1. **`xdebug_break()`** only starts a new session when `start_with_request=trigger`; inside an active session it acts as a breakpoint. Unlike Xdebug 2's `remote_mode=jit`, `start_upon_error=yes` no longer lets it start a session. 2. **CLI activation**: instead of `XDEBUG_CONFIG="idekey=name"`, set `XDEBUG_SESSION=name`. Setting `XDEBUG_CONFIG` to any value still activates the debugger as a legacy trigger. 3. **`xdebug.mode` must be set at process start**, in `php.ini` or a `conf.d` file, not in `.user.ini`, `.htaccess` or FPM `php_admin_value`. ## How Xdebug 3 reports old settings Xdebug 3 still recognises most of the old names, but only to warn about them. With `E_DEPRECATED` included in `error_reporting`, a line such as `xdebug.remote_enable=1` produces a critical diagnostic like *"The setting 'xdebug.remote_enable' has been renamed, see the upgrading guide at .../upgrade_guide#changed-xdebug.remote_enable"*. Criticals always appear in the `xdebug_info()` diagnostics log and are also written to PHP's error log. The setting itself has no effect. So the evidence is there, but only for someone who looks, which is why "the debugger does nothing" is the usual symptom. ## Migrating a config safely 1. Delete every `xdebug.remote_*`, `xdebug.profiler_enable`, `xdebug.auto_trace` and `xdebug.default_enable` line rather than leaving dead settings behind. 2. Add `xdebug.mode=debug` (plus `develop` if you want the helpers). 3. Translate host, port and discovery settings using the table above. 4. Set the IDE to listen on 9003, and check the result with `xdebug_info()`, which lists every active setting.
- A copied config sets xdebug.remote_enable=1 and nothing else. What does Xdebug 3 do with it?It does not start the debugger: `remote_enable` has no effect in Xdebug 3, and with no `xdebug.mode` set the mode stays `develop`, which has no step debugging. `xdebug_info()` shows the active mode, and its diagnostics flag the setting as renamed. The fix is `xdebug.mode=debug`.
- When does xdebug.idekey actually matter?Mainly with a DBGp proxy, which receives connections from Xdebug and routes each to the right developer's IDE by its key. In a direct one-developer setup most IDEs ignore it. Its default comes from the `DBGP_IDEKEY` environment variable, falling back to an empty string.
saying these in an interview costs you the question
- Xdebug 3 still listens on port 9000 by default
- xdebug.remote_autostart=1 still starts the debugger in Xdebug 3
- Old xdebug.remote_* settings still configure Xdebug 3
- idekey must be set for any debugging to work
- remote_connect_back was removed without replacement