PhpStorm Xdebug 3: Fix the Path Mapping Before You Edit php.ini
Most PhpStorm Xdebug failures are path-mapping problems, not php.ini problems. Validate the mapping first, then wire up Docker or CLI debugging.
07 Sept 2026, 05:30 UTC

The answer: check the path mapping before the ini file
When a breakpoint in PhpStorm 2024.x never hits, the cause is usually that PhpStorm and Xdebug disagree about which local file corresponds to which file on the server. Xdebug reports a server-side path such as /var/www/html/src/Cart.php. PhpStorm only stops if it can translate that into something like /Users/you/shop/src/Cart.php. When the translation is missing or wrong, the session connects and then ends with no visible error, which is why people keep editing php.ini in the wrong place.
PhpStorm ships a validator for exactly this: Run → Web Server Debug Validation. Run it first, fix what it reports, and only then start listening for connections.
How the mapping is decided
Xdebug opens a TCP connection to your machine and sends a file URI plus a line number. PhpStorm matches that URI against the entries in Settings → PHP → Servers. Each entry pairs a host and port with one or more path mappings: a local absolute path on one side, the server absolute path on the other.
On the first incoming request, if no server entry matches, PhpStorm offers to create one and can auto-detect the mapping from the request. That works well for a local web server where the document root and the project directory are the same folder. It works poorly for containers, where the container path has no relationship to any path on your laptop.
A worked Docker Compose setup
Assume a PHP-FPM container serving from /var/www/html, with the project bind-mounted from the host. Three things must line up: Xdebug must know where to connect, it must be told when to start, and PhpStorm must know how to translate paths.
services:
php:
image: php:8.3-fpm
environment:
XDEBUG_MODE: debug
XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9003"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./:/var/www/html
XDEBUG_MODE=debug replaces Xdebug 2's xdebug.remote_enable=1. XDEBUG_CONFIG sets the connection target. The extra_hosts entry is what makes host.docker.internal resolve on Linux; Docker Desktop on macOS and Windows provides that name automatically. Some base images instead read an XDEBUG_CLIENT_HOST variable in their entrypoint script, so check your image's documentation rather than assuming either name works.
start_with_request defaults to trigger in Xdebug 3, so a browser request only opens a session when the Xdebug Helper extension sends the trigger. That is the behaviour you want for everyday work: no trigger, no session, no slowdown.
The mapping entry PhpStorm needs
Create this under Settings → PHP → Servers. The values below assume the container is reachable at localhost:8080 and the project lives at /Users/you/shop on the host.
| Field | Value |
|---|---|
| Name | docker-php |
| Host / Port | localhost / 8080 |
| Use path mappings | checked |
| Absolute path on the server | /var/www/html |
| Project files (local) | /Users/you/shop |
The mapping is a prefix substitution, so /var/www/html/src/Cart.php resolves to /Users/you/shop/src/Cart.php. A green checkmark appears in the mapping column when PhpStorm can verify both ends exist.
Validating before you debug
- Open Run → Web Server Debug Validation and choose the local web server or Docker option that matches your setup.
- Enter the start URL and run the validation. It checks the Xdebug version, the configured port, the
modevalue, and whether a path mapping can be derived. - Set a breakpoint in a file you know is executed, click Start Listen for PHP Debug Connections (the phone icon), and load the page with the Xdebug Helper extension set to Debug and IDE key
PHPSTORM. - The Debug tool window should open at the breakpoint, with Frames, Variables, and Watches populated.
If the validator is green but the breakpoint still does not hit, enable Run → Break at first line in PHP scripts temporarily. Stopping at the first line proves the connection works and shows you the server path Xdebug reported, which you can compare against your mapping. Turn it off afterwards, because it interrupts every request.
CLI scripts need a different flag
There is no browser to send a trigger, so a CLI run must start the session explicitly for that invocation:
php -dxdebug.mode=debug -dxdebug.start_with_request=yes \
-dxdebug.client_host=host.docker.internal \
-dxdebug.client_port=9003 bin/console cache:clear
Run this inside the container if that is where your application lives. The interpreter you point PhpStorm at under Settings → PHP → CLI Interpreter must be the same PHP binary; the dialog reports the detected Xdebug version, so confirm it shows 3.x. If the script uses OpCache, a cached file can make a breakpoint appear to be skipped — setting opcache.enable_cli=0 is the usual workaround, but verify that against your own setup before relying on it.
Xdebug 2 keys that do nothing in Xdebug 3
| Xdebug 2 | Xdebug 3 equivalent |
|---|---|
xdebug.remote_enable=1 | xdebug.mode=debug |
xdebug.remote_port=9000 | xdebug.client_port=9003 |
xdebug.remote_host=... | xdebug.client_host=... |
xdebug.remote_autostart=1 | xdebug.start_with_request=yes |
Leaving the old keys in place alongside the new ones is a common cause of a session that silently never starts. Remove them rather than adding to them.
Common mistakes and limits
- Port 9003 already in use. Some PHP-FPM images bind that port themselves. If you change
xdebug.client_port, change Settings → PHP → Debug → Xdebug → Debug port at the same time, or the two ends disagree. - Mapping the wrong root. Mapping the project root to
/appwhen the container serves from/var/www/htmlproduces a connected session with no breakpoints. The validator's path mapping tab can auto-detect the correct value from an incoming request. - Assuming
host.docker.internalis universal. On plain Linux Docker it does not resolve unless you add the host-gateway entry shown above. - Two sessions at once. Concurrent debugging generally needs distinct IDE keys per session; otherwise the second connection is dropped. Treat this as an advanced case and verify it against your PhpStorm version.
Confirming it worked, and undoing the change
Confirm with php -m | grep xdebug and php -i | grep xdebug.mode inside the container, then confirm the breakpoint actually stops execution and that the Variables pane shows real values rather than a stale frame.
The Compose edit does change state, so the rollback is to remove the XDEBUG_MODE, XDEBUG_CONFIG, and extra_hosts entries and recreate the container. The PhpStorm server entry is a local setting and can be deleted from the Servers dialog without affecting the container.
Version note: this describes Xdebug 3 behaviour as used by PhpStorm 2024.x. Because Xdebug and PhpStorm both change between releases, re-run the built-in validator after any upgrade rather than assuming the previous configuration still applies.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.