This tool helps developers see and understand errors, HTTP calls, and slow database queries in WordPress.
-
Replaces the fatal error screen with a debug page that shows:
- The error message, the stack trace, and the source code around each frame, with the error line highlighted
- Data from superglobals (
$_REQUEST,$_SERVER,$_FILES,$_COOKIE,$_SESSION) - A “Copy for AI” button and an “Ignore error” button (sets the
wp_debugger_ignorecookie, so the page does not show again)
-
Shows errors as JSON for WP-CLI requests and for requests that send or accept
application/json -
Logs outgoing HTTP requests and responses, and can return mock responses (see HTTP debugging)
-
Finds repeated (N+1) and slow database queries (see Query detector)
-
Saves logs in
wp-content/logs/. When a log file gets bigger than 1 MB, it is emptied (no backup copies)
Requires PHP 8.0 or newer.
- Put the plugin folder into
wp-content/plugins/wp-debugger/ - Activate it in WordPress. Activation copies
stubs/mu-loader.stubtowp-content/mu-plugins/000-wp-debugger.php, so the plugin loads before other plugins and catches their errors. Deactivation removes that file, but only if you did not change it. - To stop the plugin for one request, add
?disable_debugto the URL
-
Cause a fatal error or throw an exception to see the debug page
-
Use these helper functions from
functions.php:write_log( ...$messages )— saves each message towp-content/logs/0-debugger.logdump( ...$vars )— shows data as an HTML page, or as pretty JSON in CLIdd( ...$vars )— dump, then stopdump_filter_callbacks( $filter, $dump = true )— shows the callbacks on a hook. Passfalseto write them to the log insteadrecursively_decode_json( $data )— turns nested JSON strings into arrays, so logs stay readabledebugger_format_variable( ...$messages )— formats values for the log (arrays and JSON pretty-printed, objects shown as class name)is_terminal_request()—truefor CLI and WP-CLI
- Uses
http_api_debugto log each outgoing request (URL, method, timeout, headers that cURL actually sent, body) and its response - Logs go to
wp-content/logs/{host}-requests.log. Failed requests (WP_Error) go to{host}-errors.log - Requests to the site's own URL are not logged
Set define( 'ENABLE_MOCK_HTTP_INTERCEPTOR', true ); to return fake JSON responses instead of making real requests.
- Default mocks: Akismet
comment-checkand WordPress.orgcore/version-check - Add or change mocks with the
wp_debugger_mock_urlsfilter. Keys are URLs and can usefnmatchwildcards (for examplehttps://api.example.com/*). Values are the response data, or aWP_Error - Mock responses have the header
x-mock-response: true - URLs without a mock make a real request, and are written to
0-debugger.log
-
Turns on
SAVEQUERIES(unless it is already defined) and checks all queries atshutdown -
Flags the same query shape from the same caller that runs 5 or more times (N+1), and any query that takes 0.05 seconds or more
-
Writes results to
wp-content/logs/query-detector.log -
In CLI, prints a summary. In the browser, shows an admin notice on the next admin page load
-
Filters:
wp_debugger_n1_threshold— repeat count that flags a query (default5)wp_debugger_slow_query_threshold— slow query time in seconds (default0.05)wp_debugger_n1_caller_filter— string or array of caller names. Only queries from matching callers are checked
-
Does not run under Pest or PHPUnit