How do you use xdebug_info() and xdebug.log to find out why an Xdebug 3 step-debugging session never starts?
answer
- phpinfo() for Xdebug
- xdebug_info('mode') returns an array
- log needs a writable absolute path
- log_level 7 default, 10 for breakpoints
- trigger not found, NOCON, TIMEOUT
basics
~20 sCall xdebug_info() from the same SAPI to confirm debug mode, the effective settings and recent errors, then set xdebug.log to a writable file; its entries show whether the trigger was found and which host and port Xdebug tried and why it failed.
solid answer
~40 sWork through the chain in order. First, `xdebug_info()` from a web request, not the CLI, because FPM may load different ini files: it shows whether Xdebug is loaded, the active modes (`xdebug_info('mode')` returns them as an array), every setting's effective value, and a diagnostics log of recent warnings. Second, set `xdebug.log=/tmp/xdebug.log`, an absolute path the PHP user can write. At the default `log_level` 7 it records `Trigger value for 'XDEBUG_SESSION' not found, so not activating` when no trigger arrived, `Connecting to configured address/port: host:9003`, and then `Connected to debugging client`, or an error such as `NOCON` (refused, nothing listening) or `TIMEOUT` (no answer within `connect_timeout_ms`). Raise `log_level` to 10 to see breakpoint resolution once connected. Each logged problem links to Xdebug's error-code documentation.
code
ini · 3 linesxdebug.mode=debug
xdebug.log=/tmp/xdebug.log
xdebug.log_level=10 ; default 7; 10 adds breakpoint resolvinggo deeper
Recall that xdebug_info() shows Xdebug's active modes and settings, and that xdebug.log records connection attempts.
Explain the SAPI trap, how to read trigger-not-found, NOCON, TIMEOUT and Connected lines, and when to raise log_level to 10.
Show you diagnose link by link from evidence rather than guessing, and clean up diagnostic pages and verbose logs afterwards.
Build these checks into the team's development tooling, such as a health endpoint in dev images, so setup failures diagnose themselves.
## Think of it as a chain A step-debugging session needs every link to hold: 1. Xdebug is **loaded** in the PHP that serves the request. 2. **Debug mode** is active (`xdebug.mode` includes `debug`). 3. The request **asks** for a session (a trigger, or `start_with_request=yes`). 4. Xdebug **reaches** the IDE at `client_host:client_port`. 5. The IDE's **breakpoints** match files Xdebug knows. Guessing wastes time. Xdebug's two diagnostic tools tell you which link broke. ## Tool 1: xdebug_info() `xdebug_info()` is Xdebug's equivalent of `phpinfo()`: - called with no argument, it outputs a page showing the Xdebug version, which **modes** are enabled, every `xdebug.*` setting with its effective value, and a **diagnostics log** of recent warnings and errors, each linked to its documentation; - `xdebug_info('mode')` (Xdebug 3.1+) returns an array of the enabled modes, handy in a test or health check. Two rules make it useful: - **Call it from the same SAPI you are debugging.** The CLI and PHP-FPM often load different ini files, so `php -r 'xdebug_info();'` can show `debug` while the web server's PHP shows `develop`. Put a temporary `<?php xdebug_info();` page behind the same web server and remove it afterwards, since it exposes configuration. - If the page shows no Xdebug section at all, the extension is not loaded for that SAPI. That is an ini-loading problem, not a debugger one. ## Tool 2: xdebug.log `xdebug.log` takes an **absolute path** the PHP process user can create and write, such as `/tmp/xdebug.log`. The file is opened in append mode. On systemd hosts, a service with a private `/tmp` may write it somewhere unexpected. `xdebug.log_level` selects detail: | Level | Name | Adds | |---|---|---| | 0 | Criticals | configuration errors | | 1 | Errors | connection errors | | 3 | Warnings | connection warnings | | 5 | Communication | DBGp protocol messages | | **7** | Information | connection progress (the default) | | 10 | Debug | breakpoint resolving | ## Reading the log Typical lines, keyed to the chain above: - `Trigger value for 'XDEBUG_SESSION' not found, so not activating`: link 3. No cookie, GET, POST or environment trigger arrived. Check the browser extension or `XDEBUG_SESSION=1` on the CLI, and `xdebug.trigger_value` if one is set. - `Connecting to configured address/port: localhost:9003.` followed by `Could not connect to debugging client. Tried: ...` (**NOCON**): link 4. Nothing is listening there, or the host is wrong, which is common in containers where `localhost` is the container. - `Time-out connecting to debugging client, waited: 200 ms` (**TIMEOUT**): link 4. A firewall is silently dropping packets, or the network is slow; fix the network first, and only then consider raising `connect_timeout_ms`. - `Connected to debugging client: ...`: links 1 to 4 hold. If nothing stops, go to link 5 with `log_level=10`. A breakpoint set on a file that does not exist from Xdebug's point of view means the IDE's path mapping is wrong. Criticals and errors are also written to PHP's own `error_log`, and they appear in the `xdebug_info()` diagnostics even without `xdebug.log`. ## Worked example A developer reports "the debugger never stops". `xdebug_info()` from the site shows mode `debug` and `client_host` `localhost`. The log shows the trigger found, then `Could not connect to debugging client. Tried: localhost:9003`. PHP runs in a container, so `client_host` must point to the host. After changing it, the log shows `Connected`, and the first breakpoint hits. ## Related runtime checks - `xdebug_is_debugger_active()` returns `true` only while a DBGp client is attached, which is useful in a temporary guard or log line. - `xdebug_break()` returns `false` when no session was active and none could be started, so logging its result in a stubborn code path shows whether the connection or the breakpoint is the problem. - `xdebug.start_upon_error=yes` is a quick way to test connectivity: trigger a warning and see whether the IDE wakes up. ## Clean up afterwards - Remove any public `xdebug_info()` page. - Turn the log off or lower `log_level`, since a DBGp-level log grows quickly.
- Why can php -r 'xdebug_info();' on the command line mislead you about a web request?The CLI and PHP-FPM are separate SAPIs and often read different ini files or conf.d directories. The CLI may have `xdebug.mode=debug` while FPM still runs `develop`, or has no Xdebug at all. Always check `xdebug_info()` from a request served by the same web server and PHP-FPM pool you are debugging.
- Your xdebug.log stays empty although xdebug.log is set. What are the usual causes?The PHP process user, such as `www-data`, cannot create or write the file; the path is relative instead of absolute; or a systemd-managed service has a private `/tmp`, so the file lands in a different directory. The `xdebug_info()` diagnostics section shows the file-open error in that case.
saying these in an interview costs you the question
- xdebug_info() on the CLI proves the web server's configuration
- xdebug.log accepts a path relative to the project
- An empty log means the connection succeeded
- Raise connect_timeout_ms first when the log says NOCON
- log_level 10 is the default