Skip to main content

Troubleshooting

Almost every "the debugger does not work" report is one of three things: it is not running, it is running but cannot reach your editor, or it reaches your editor and the breakpoints do not match your files. This page walks those in order.

Start here: is it loaded?​

Before anything else, confirm the debugger is present in the PHP that is actually running your code:

php -v

You are looking for a line like this among the ones that follow the version:

with PHP Debugger v0.3.0, Copyright (c) 2002-2026, by Derick Rethans

If it is not there, nothing else on this page will help until it is.

Using the interpreter with the debugger built in? Then that line is always present, so its absence means you are running a different PHP from the one you think. Check with which php, and remember that your web server, your container and your shell can each have their own.

Using the extension? Look above the version output for a loading error. A line starting Failed loading names the problem directly — a path that does not exist, or a build that does not match this PHP. An extension has to be built for the same PHP version, and the same thread-safety and debug settings; a mismatch will not load. If there is no error at all, the extension is simply not being loaded, so check that a zend_extension= line for it exists in a file this PHP actually reads — php --ini lists them.

If none of that gets it loaded, start again from Installation, which covers each way of installing it and what that puts where.

Then ask the debugger​

With it loaded, ask the debugger what it thinks is going on before changing any settings. Put this somewhere the request will reach:

php_debugger_info();

It prints a page telling you whether the debugger is loaded, what mode it is in, whether a session is active, and — if one is — which client it connected to.

The part worth scrolling to is Diagnostic Log. It lists every warning and error the debugger raised during this request, with a link explaining each one. A refused connection, a rejected trigger value, an unreadable log file: they all show up here without you configuring anything first.

If that page does not appear at all, the debugger is not loaded after all, whatever php -v seemed to say — most likely the request is being served by a different PHP from the one you checked. Go back to the section above.

Nothing happens at all​

No connection attempt, no error, nothing in your editor.

Check the mode. php_debugger.mode has to be debug, which is the default. If something set it to off, the debugger does nothing and says nothing.

Check nothing else is loaded alongside it. PHP Debugger takes the place of Xdebug and the two cannot both be loaded. A leftover zend_extension=xdebug.so line is the usual culprit — one of the two loses, and which one is not something to rely on. Look for it in every file, not just php.ini: distributions scatter conf.d snippets, and Docker images add their own.

Check a session is meant to start. By default every request starts one. If php_debugger.start_with_request has been set to trigger, nothing happens without a trigger present; if it is no, nothing happens at all. See starting the debugger.

It tries to connect but nothing arrives​

This is the common one, and the log answers it directly. Point it at a file:

php_debugger.log=/tmp/php-debugger.log

Then make a single request and read what it wrote. At the default level there is a line for every connection attempt, saying where it tried and whether it worked, and that one line usually ends the investigation.

"Connecting to configured address/port" and then nothing means the address is wrong or nothing is listening. Two things to confirm, in this order: that your editor is actually listening — most only listen while you have started a listening session, not merely because the editor is open — and that php_debugger.client_host names a machine your code can reach. Inside a container localhost is the container itself, which is the single most frequent cause. See connecting to a client.

No connection line at all means the debugger never got as far as trying. Go back to the section above — this is a session that never started, not a connection that failed.

It connects but breakpoints do not fire​

The session is live, stepping might even work, but your breakpoints are ignored.

Path mapping is the first suspect. The debugger reports paths as the machine running your code sees them. When that is a container, or another machine, those are not the paths your editor knows, and a breakpoint set on /home/you/project/src/Foo.php means nothing to a debugger running /var/www/src/Foo.php. Your editor has a path mapping setting for exactly this; it needs to know that one directory corresponds to the other. Nothing about this is configured in php.ini.

The line may not be executable. Blank lines, comments, closing braces and use statements are never reached. Most editors move the marker or mark the breakpoint unverified — if yours shows breakpoints as resolved or unresolved, trust that signal.

A condition may never be true. An expression that cannot be evaluated in that scope counts as false and fails silently, so a typo in a condition looks exactly like a breakpoint that does not work. Remove the condition and see if it fires.

The file may not be the one running. A stale OPcache copy, a deployed build rather than your working tree, a vendored duplicate of the class you think you are editing. Set a breakpoint on the first line of the file and, if it fires, look at the path the debugger reports.

It works, but everything is slow​

Look for breakpoints you have forgotten. Every one is checked on every request, and a list built up over an afternoon is not free. Delete rather than disable.

Check php_debugger.on_demand_debugging_enabled. If it is on, every request is compiled with debugging instrumentation whether or not it is debugged, which costs roughly half the benefit of using this debugger at all. Turn it off unless you genuinely need to attach mid-request.

Still stuck​

Raise php_debugger.log_level to 10 and make one request. That level records the decisions leading up to a session — each trigger it checked for, each configuration value it resolved — so it answers "why did it not even try" rather than "why did the attempt fail".

If you are certain the debugger and your editor are talking but disagreeing, level 5 logs every protocol message in both directions. It is verbose and it is the right tool for exactly one question: what was actually sent.

Both are described on the logging page. A log from level 10, with the request you made and what you expected, is also the most useful thing you can attach to a bug report.