skip to content

How do you use xdebug_info() and xdebug.log to find out why an Xdebug 3 step-debugging session never starts?

level: middleimportance: should knowfreq 30%

answer

  1. phpinfo() for Xdebug
  2. xdebug_info('mode') returns an array
  3. log needs a writable absolute path
  4. log_level 7 default, 10 for breakpoints
  5. trigger not found, NOCON, TIMEOUT

basics

~20 s

Call 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 s

Work 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 lines
ini
xdebug.mode=debug
xdebug.log=/tmp/xdebug.log
xdebug.log_level=10   ; default 7; 10 adds breakpoint resolving

go deeper

for a junior

Recall that xdebug_info() shows Xdebug's active modes and settings, and that xdebug.log records connection attempts.

for a middle

Explain the SAPI trap, how to read trigger-not-found, NOCON, TIMEOUT and Connected lines, and when to raise log_level to 10.

for a senior

Show you diagnose link by link from evidence rather than guessing, and clean up diagnostic pages and verbose logs afterwards.

for a principal

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