WordPress ships with a set of PHP constants you define in wp-config.php to control debug output, logging behavior, script loading, and query tracking. Most developers know WP_DEBUG and stop there. The full set of debug constants gives you much finer control: log errors to a file without displaying them to visitors, load unminified scripts for easier debugging, record every database query with its execution time, and redirect PHP error output to a custom location. This guide documents every debug constant WordPress supports, what each one does, and exactly how to configure them for different scenarios.
Where to Set Debug Constants
All WordPress debug constants are defined in wp-config.php, the configuration file at the root of your WordPress installation. The constants must be defined before the line that includes wp-settings.php. WordPress reads these constants during bootstrap and configures PHP error handling and the script loader based on their values.
A typical debug block in wp-config.php looks like the snippet below. The exact constants you enable depend on your current task: development, staging, or production environments each call for different configurations.
Constants defined with define() cannot be overridden by plugins or themes, once a constant is set in wp-config.php it is fixed for the entire request lifecycle. This is intentional: debug configuration should be controlled at the infrastructure level, not by application code.
WP_DEBUG
What It Does
WP_DEBUG is the master debug switch. When set to true, it configures PHP’s error reporting level to E_ALL, which causes PHP to surface every notice, warning, and deprecated message that would otherwise be silently swallowed. Without WP_DEBUG enabled, PHP silences notices and many warnings by default, which means bugs in plugins and themes can hide for months before they manifest as visible errors.
Default value: false
What Changes When WP_DEBUG is True
- PHP error reporting is set to
E_ALL - PHP display_errors is set to
1(errors shown in browser) unlessWP_DEBUG_DISPLAYoverrides this - WordPress’s own deprecation notices (functions marked
_deprecated_function()) are triggered - Theme and plugin compatibility notices appear
wp_debug_backtrace_summary()output is included in some error messages
Production Warning
Never set WP_DEBUG to true on a live production site unless you also set WP_DEBUG_DISPLAY to false and WP_DEBUG_LOG to true. With WP_DEBUG alone, PHP error messages display in the browser, visitors see raw PHP output, which exposes file paths, variable names, and potentially sensitive application logic.
WP_DEBUG_LOG
What It Does
WP_DEBUG_LOG redirects PHP errors to a log file instead of (or in addition to) displaying them in the browser. When set to true, errors are written to wp-content/debug.log. When set to a string file path, errors are written to that path instead.
Default value: false
Custom Log Path
Setting WP_DEBUG_LOG to a full file path is preferable in production environments where you want error logging without the default log being publicly accessible. The default wp-content/debug.log is web-accessible unless your server configuration blocks it, a visitor who knows or guesses the path can read your error log, which may expose database query details, file paths, and plugin version information.
Alternatively, use ini_set to route PHP’s error_log to a location outside the web root entirely. This approach works independently of WP_DEBUG_LOG and gives you direct control over PHP’s error logging at the ini level:
Relationship with WP_DEBUG
WP_DEBUG_LOG works independently of WP_DEBUG. You can enable error logging without enabling full debug mode. However, the errors that get logged depend on PHP’s current error reporting level, if WP_DEBUG is false, PHP is only reporting errors above a certain severity threshold, and notices/warnings may not appear in the log even with WP_DEBUG_LOG enabled. For comprehensive logging, set both constants.
WP_DEBUG_DISPLAY
What It Does
WP_DEBUG_DISPLAY controls whether PHP errors are shown in the browser. It only has meaning when WP_DEBUG is true. When WP_DEBUG_DISPLAY is false, errors are suppressed from browser output even though PHP is reporting them at the E_ALL level.
Default value: true (when WP_DEBUG is true)
The Standard Production Logging Config
The combination of WP_DEBUG = true, WP_DEBUG_LOG = true, and WP_DEBUG_DISPLAY = false is the standard configuration for capturing errors silently on production or staging. This logs all PHP errors, warnings, and notices to debug.log without exposing them to visitors. Use this configuration on staging environments where you want to catch issues that only appear with real data and real traffic patterns, without affecting the visitor experience.
SCRIPT_DEBUG
What It Does
SCRIPT_DEBUG forces WordPress to load the unminified, development versions of core JavaScript and CSS files instead of the minified production versions. When true, WordPress loads files like wp-admin/js/common.js instead of wp-admin/js/common.min.js.
Default value: false
When to Use SCRIPT_DEBUG
Enable SCRIPT_DEBUG when:
- Debugging JavaScript errors in wp-admin, the minified files are obfuscated and hard to trace
- Setting breakpoints in browser DevTools on WordPress core JS files
- Investigating a CSS issue in wp-admin that might originate from core stylesheets
- Debugging the block editor, Gutenberg’s core scripts are significantly easier to read unminified
SCRIPT_DEBUG is independent of WP_DEBUG. You can enable it without enabling PHP error reporting. This is useful for frontend JavaScript debugging where you don’t need the noise of PHP notices cluttering your error log.
Performance Impact
The unminified scripts are significantly larger. On admin pages, SCRIPT_DEBUG increases total JavaScript payload by 3-5x. This is only relevant on your local or staging environment, never enable SCRIPT_DEBUG in production. The performance impact does not affect frontend pages unless your theme or plugins enqueue admin scripts on the frontend.
SAVEQUERIES
What It Does
SAVEQUERIES enables WordPress’s built-in query logging. When true, every database query executed during a page load is stored in the $wpdb->queries global array along with the query string, its execution time in seconds, and the function call stack that triggered it.
Default value: false
Accessing the Query Log
With SAVEQUERIES enabled, inspect the query log in a footer action or via a plugin. Each entry in $wpdb->queries is an array with three elements: the SQL query string, the execution time, and the backtrace of PHP functions that triggered the query.
In practice, Query Monitor provides a much better interface for inspecting queries than reading the raw $wpdb->queries array, it organizes queries by calling component, highlights duplicates, flags slow queries, and shows execution time per query in a sortable table. If you have Query Monitor installed, enabling SAVEQUERIES is not necessary just to browse queries, Query Monitor hooks into $wpdb independently. However, SAVEQUERIES is useful when you want to process the query log programmatically in custom debugging code. For a complete walkthrough of Query Monitor’s query panel and all its other capabilities, see the Query Monitor complete developer tutorial.
Performance Impact
SAVEQUERIES adds overhead to every database query, each query’s execution time is measured, its backtrace is captured, and the results are stored in an in-memory array that grows throughout the request. On pages with 50-100 database queries (typical for WordPress with several plugins), the memory overhead is modest but measurable. Disable SAVEQUERIES when you finish debugging, never leave it enabled in production.
WP_CACHE
What It Does
WP_CACHE controls whether WordPress loads the advanced cache drop-in. When true, WordPress includes wp-content/advanced-cache.php very early in the bootstrap process, before any plugins load, allowing full-page caching solutions to intercept the request and serve a cached response without completing the full WordPress bootstrap.
Default value: false
How Full-Page Caching Uses WP_CACHE
Caching plugins like WP Rocket, W3 Total Cache, and LiteSpeed Cache rely on WP_CACHE = true to serve cached pages. When you install these plugins, they set WP_CACHE = true in wp-config.php automatically and create their own advanced-cache.php drop-in. The drop-in checks whether the requested URL has a cached copy and, if so, outputs the cached HTML and exits before WordPress finishes loading. This is what allows cached TTFB to reach 5-20ms, the full WordPress stack never runs for cached requests.
If you disable a caching plugin but WP_CACHE remains true and the advanced-cache.php file still exists, WordPress will load that file on every request. Most caching plugins clean up their drop-in on deactivation, but if the file is left behind after manual plugin deletion, you may see unexpected behavior. Check wp-content/advanced-cache.php any time you troubleshoot caching issues.
WP_CACHE and Object Caching
WP_CACHE is specifically for the full-page cache drop-in. It is unrelated to WordPress’s object cache drop-in (wp-content/object-cache.php), which enables persistent object caching via Redis or Memcached. The object cache drop-in is loaded regardless of the WP_CACHE constant’s value, WordPress always checks for and loads object-cache.php if it exists.
CONCATENATE_SCRIPTS
What It Does
CONCATENATE_SCRIPTS controls whether WordPress combines (concatenates) multiple admin JavaScript files into a single request. When false, each script is loaded separately. This constant only affects wp-admin pages and the script loading behavior there.
Default value: true in wp-admin
When to Disable Script Concatenation
Disable script concatenation when debugging JavaScript errors in wp-admin. When scripts are concatenated, a JavaScript error in one file can break all scripts in the combined bundle, making it difficult to identify which script is the source. With concatenation disabled, each script loads individually, and browser DevTools shows the exact file and line number of the error.
This is one of the first steps when debugging “white screen” or broken UI issues in the WordPress admin, disable concatenation, reload the page, and check the browser console for specific script errors with proper file attribution.
COMPRESS_SCRIPTS and COMPRESS_CSS
What They Do
COMPRESS_SCRIPTS and COMPRESS_CSS control whether WordPress gzip-compresses concatenated scripts and stylesheets before serving them from wp-admin. Both default to true in wp-admin when compression is available. Set to false to disable compression for debugging purposes.
These constants are rarely needed in day-to-day debugging. They matter primarily when diagnosing issues with gzip compression at the application level conflicting with server-level gzip, which can result in double-compressed content that browsers cannot parse. If you see garbled script output or CSS that appears to be binary data, disable these constants to rule out double compression.
WP_LOCAL_DEV
What It Does
WP_LOCAL_DEV is a flag constant that indicates the current environment is a local development installation. WordPress core uses it in a few places to adjust behavior for local development, for example, automatic update behavior. It is primarily useful for custom code that needs to behave differently on local versus staging versus production environments.
Unlike the other debug constants, WP_LOCAL_DEV does not activate any WordPress functionality by itself. It is a signal constant for code that checks defined('WP_LOCAL_DEV') && WP_LOCAL_DEV to alter its behavior in local environments. Use it in your own code to guard development-only behavior, disabling email sends, bypassing external API calls, or loading fixtures instead of live data.
DOING_CRON
What It Does
DOING_CRON is set to true by WordPress core when a WP-Cron request is running. It is not a constant you define in wp-config.php, WordPress sets it internally. However, understanding it is important for debugging: many plugins and themes check defined('DOING_CRON') && DOING_CRON to skip certain operations during cron runs (outputting HTML, starting sessions, or triggering user-facing actions). If a scheduled task is not behaving as expected, check whether the code checks this constant and adjusts its behavior.
DOING_AJAX
What It Does
Like DOING_CRON, DOING_AJAX is set by WordPress core during AJAX requests (requests to wp-admin/admin-ajax.php). It is useful for debugging AJAX handlers, you can check this constant to confirm your handler is actually receiving AJAX requests and not being called in a different context. Understanding these runtime constants is part of reading WordPress execution flow correctly when errors surface in unexpected request types.
Using ini_set for Custom Error Log Paths
WordPress’s debug constants configure error reporting at the WordPress level, but PHP’s own error logging is configured via php.ini or ini_set(). The two systems overlap: when WP_DEBUG_LOG is set to a file path, WordPress calls ini_set('error_log', $path) internally. You can bypass this and set the error log path yourself for more granular control.
The ini_set approach in wp-config.php is particularly useful when your WordPress debug log configuration needs to match a log aggregation setup (sending errors to a specific path that a monitoring agent like Datadog or Loggly is tailing). It also works when you need different log files for different severity levels, route PHP fatals to one file and notices/warnings to another by using custom error handlers alongside set_error_handler().
Environment-Specific Debug Configurations
Local Development
On local development, you want maximum visibility into errors. Show all errors in the browser and log them to a file. This configuration catches both PHP errors and WordPress-level notices and deprecation warnings:
Staging
On staging, you want full error logging without displaying errors to anyone who accesses the staging site during testing. Log everything silently, review the debug log regularly:
Production
On production, WP_DEBUG should typically be false. If you need to capture errors without affecting users, use the production logging configuration that keeps errors silent but logged:
Reading debug.log Effectively
The debug.log file grows quickly on active sites with errors. Raw PHP errors look like this:
Each entry includes the severity level (PHP Notice, PHP Warning, PHP Fatal error, PHP Deprecated), the message, the file path, and the line number. For a full breakdown of what each severity level means and how to read stack traces, see the complete guide to reading WordPress error logs. This paired article covers how to decode PHP error types, read backtrace output, and map common WordPress errors to their root causes.
Debugging with wp_debug_backtrace_summary()
WordPress provides a helper function for generating abbreviated call stack summaries: wp_debug_backtrace_summary(). It returns a comma-separated string of the function names in the current call stack, useful for logging where a specific WordPress event was triggered from without the verbosity of a full PHP backtrace.
This function is used internally by WordPress’s _deprecated_function(), _deprecated_argument(), and _doing_it_wrong() to include call context in deprecation notices. You can use it in your own debug logging hooks to add calling context to custom log entries.
_doing_it_wrong() and WordPress Notices
Beyond PHP-level errors, WordPress has its own system for flagging incorrect usage: _doing_it_wrong(). This function triggers a doing_it_wrong_run action and, if WP_DEBUG is enabled, outputs a notice like: “WordPress function get_the_title() was called incorrectly. Post title should not be retrieved inside this hook.” These notices do not indicate PHP errors, they are WordPress’s way of enforcing correct API usage. When WP_DEBUG is true, you will see these notices in the browser or in the error log, and they often point to plugin or theme code that is hooking into the wrong action, calling functions too early, or misusing WordPress core APIs.
Complete Debug Constants Reference
| Constant | Type | Default | What It Controls |
|---|---|---|---|
WP_DEBUG | bool | false | Master debug switch. Sets PHP error reporting to E_ALL. |
WP_DEBUG_LOG | bool / string | false | Log errors to wp-content/debug.log or a custom path. |
WP_DEBUG_DISPLAY | bool | true | Show errors in browser (only when WP_DEBUG is true). |
SCRIPT_DEBUG | bool | false | Load unminified JS/CSS for WordPress core assets. |
SAVEQUERIES | bool | false | Store all DB queries in $wpdb->queries with timing and backtraces. |
WP_CACHE | bool | false | Load wp-content/advanced-cache.php (full-page cache drop-in). |
CONCATENATE_SCRIPTS | bool | true | Concatenate admin JS files into single request. |
COMPRESS_SCRIPTS | bool | true | Gzip compress concatenated admin scripts. |
COMPRESS_CSS | bool | true | Gzip compress concatenated admin CSS. |
WP_LOCAL_DEV | bool | undefined | Flag for local development environment detection. |
Frequently Asked Questions
Can I enable WP_DEBUG on a live site?
Only if you also set WP_DEBUG_DISPLAY = false and WP_DEBUG_LOG = true. This captures errors silently without exposing them to visitors. The recommended approach on live sites is to use a log aggregation solution and review debug.log periodically rather than enabling debug mode at all.
Does WP_DEBUG slow down my site?
Minimally. WP_DEBUG changes PHP’s error reporting level and triggers WordPress deprecation notices, but these are lightweight operations. The noticeable performance impact comes from SAVEQUERIES (memory overhead per query) and the deprecation notice system on sites with many plugins that trigger frequent _doing_it_wrong() calls. On local development, the overhead is inconsequential. On production, avoid SAVEQUERIES entirely.
Why is my debug.log not being created?
Three common causes: (1) WP_DEBUG is false, so PHP is not reporting notices and warnings that would be logged, set WP_DEBUG = true to enable full error reporting. (2) The wp-content directory is not writable by the web server user, check directory permissions. (3) A php.ini setting is overriding the error_log path, check phpinfo() output for the active error_log value.
Does SAVEQUERIES work without Query Monitor?
Yes. SAVEQUERIES is a WordPress core feature that stores queries in $wpdb->queries without any plugins. Query Monitor uses its own query tracking mechanism and provides a richer interface, but SAVEQUERIES is independent and works without any plugins installed. Use it when you need to access query data programmatically in custom code.
Getting comfortable with WordPress’s debug constants turns debugging from guesswork into a systematic process. Enable WP_DEBUG and WP_DEBUG_LOG on development and staging as a default, keep WP_DEBUG_DISPLAY false on anything with public access, and use SAVEQUERIES and SCRIPT_DEBUG as targeted tools for specific investigations. The constants take two minutes to configure and can save hours of blind troubleshooting. For the next step in WordPress debugging, the Query Monitor developer tutorial covers every panel of the plugin that complements these debug constants with real-time visual debugging in the admin bar.
PHP error logging SAVEQUERIES WordPress Debugging WP_DEBUG wp-config.php
Last modified: March 30, 2026