WordPress has a built-in debug mode that activates PHP error reporting, writes errors to a log file, and optionally displays them in the browser. WP Debug Toolkit (WPDT) gives you toggle switches and WP-CLI commands to control these settings without editing files manually.
If you only remember one thing: WP_DEBUG activates error reporting. WP_DEBUG_LOG writes errors to a file. WP_DEBUG_DISPLAY shows errors in the browser. You almost always want the first two on and the third one off.
WordPress debug mode is controlled by three PHP constants defined in wp-config.php. Each one does something different, and they work independently of each other.
define('WP_DEBUG', true);
This is the master switch. When set to true, WordPress tells PHP to report all errors, warnings, notices, and deprecation messages. When set to false (the default), WordPress suppresses most error output.
With WP_DEBUG enabled, you see errors that would otherwise be silently ignored — undefined variables, deprecated function calls, missing arguments, type mismatches. These are not necessarily breaking your site, but they indicate problems that may cause issues later.
WP_DEBUG on its own does not write anything to a file. It only activates error reporting. Where those errors go depends on the next two constants.
define('WP_DEBUG_LOG', true);
When set to true, WordPress writes all reported errors to a log file at wp-content/debug.log. This is the file you check when something goes wrong.
You can also set WP_DEBUG_LOG to a file path string instead of true:
define('WP_DEBUG_LOG', '/home/user/logs/wordpress-errors.log');
This writes errors to that path instead of the default wp-content/debug.log. Some managed hosts set this automatically to redirect logs to their own location.
WP_DEBUG_LOG requires WP_DEBUG to be true. If WP_DEBUG is false, setting WP_DEBUG_LOG to true has no effect — there are no errors being reported to log.
define('WP_DEBUG_DISPLAY', false);
The default is true. When you enable WP_DEBUG without explicitly setting WP_DEBUG_DISPLAY to false, errors appear in the browser.
When set to true, PHP errors are printed directly into your site’s HTML output. Visitors see raw error messages in their browser. When set to false, errors are suppressed from the screen but still get logged (if WP_DEBUG_LOG is on).
On a production site, WP_DEBUG_DISPLAY should always be false. Displaying errors to visitors leaks file paths, function names, and database details. It also breaks page layouts when warnings appear in the middle of rendered HTML.
On a local development environment, setting it to true is fine — it lets you see errors inline as you code.
| WP_DEBUG | WP_DEBUG_LOG | WP_DEBUG_DISPLAY | Result |
|---|---|---|---|
false | any | any | Debug mode off. Most errors suppressed. |
true | false | false | Errors reported internally but not logged or displayed. Limited use. |
true | true | false | Errors logged to file, hidden from visitors. The production setting. |
true | true | true | Errors logged to file and shown in browser. The development setting. |
true | false | true | Errors shown in browser but not logged. Risky and not recommended. |
This method works on any WordPress site, regardless of what plugins you have installed.
The file is in your WordPress root directory (the same directory that contains wp-content/, wp-admin/, and wp-includes/). Connect to your server via FTP, SFTP, or SSH, or use your hosting control panel’s file manager.
Open wp-config.php in a text editor. Find the line that reads:
/* That's all, stop editing! Happy publishing. */
Add the following constants above that line:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
If the constants already exist in the file, change their values instead of adding duplicates. Having the same constant defined twice causes a PHP notice and the second definition is ignored.
Save the file and upload it back to the server (if editing via FTP). Reload any page on your site to trigger WordPress to start logging errors.
WordPress creates wp-content/debug.log (if it does not already exist) and begins writing error entries to it. The file grows over time as new errors are reported.
A typical log entry looks like this:
[15-Mar-2026 09:21:33 UTC] PHP Warning: Undefined variable $user_name in /wp-content/plugins/example-plugin/includes/class-profile.php on line 84
This tells you: the error type (Warning), what went wrong (undefined variable), the file path, and the line number.
WPDT manages these constants through a UI, so you do not need to edit wp-config.php by hand.
WP_DEBUG and WP_DEBUG_LOG to true.WP_DEBUG_DISPLAY set to false).WPDT writes the changes to wp-config.php automatically. It creates a backup of the file before making changes.
If WordPress is down or you cannot access the admin dashboard:
https://example.com/wpdebugtoolkit/).K to open Settings.The viewer writes directly to wp-config.php through its own API — no WordPress required.
wp dbtk debug on
This enables WP_DEBUG and WP_DEBUG_LOG. To also enable WP_DEBUG_DISPLAY:
wp dbtk debug on --display
Check the current state:
wp dbtk debug status
Output:
+--------------------+-----------------------------------+
| Setting | Value |
+--------------------+-----------------------------------+
| WP_DEBUG | ON |
| WP_DEBUG_LOG | ON |
| WP_DEBUG_DISPLAY | OFF |
| SAVEQUERIES | OFF |
| Enhanced logging | OFF |
| Log path | /var/www/html/wp-content/debug.log|
+--------------------+-----------------------------------+
After enabling debug mode, confirm that errors are being logged.
Look for wp-content/debug.log on the server. If the file does not exist yet, no errors have been reported since you enabled debug mode.
On a staging or development site, you can force an error to confirm logging works. Add this line temporarily to your theme’s functions.php:
error_log('WPDT test: debug logging is working');
Reload the site, then check debug.log. You should see an entry like:
[15-Mar-2026 09:25:00 UTC] WPDT test: debug logging is working
Remove the test line after confirming.
In the standalone viewer, navigate to Error Logs. If logging is working, you see entries appearing. If the log is empty, the test error above confirms whether the logging pipeline is connected.
The right debug configuration depends on where the site is running.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Log errors to a file. Never show them to visitors. This gives you a record of problems without exposing server details to the public.
Some developers set WP_DEBUG to false on production. This means you get no error logging at all — problems happen silently and you find out when a client reports a broken page. Keeping WP_DEBUG and WP_DEBUG_LOG on while keeping WP_DEBUG_DISPLAY off is the safer approach.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
Show errors directly in the browser so you catch problems as you work. Also log to file so you have a record.
Same as staging, but you can also enable SCRIPT_DEBUG and SAVEQUERIES for deeper insight:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
define('SCRIPT_DEBUG', true);
define('SAVEQUERIES', true);
SCRIPT_DEBUG loads unminified versions of core CSS and JS files. SAVEQUERIES stores all database queries in memory for analysis (see How to Find Slow Database Queries).
If you enabled debug mode for a specific troubleshooting session, disable it when you are finished.
Open wp-config.php and change:
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
Or remove the lines entirely. WordPress defaults to false for all three when they are not defined.
Toggle the switches off in Debug Toolkit → Overview, or run:
wp dbtk debug off
On production, keeping WP_DEBUG and WP_DEBUG_LOG on with WP_DEBUG_DISPLAY off is a reasonable permanent configuration. The performance impact is minimal, and you always have a log to check when problems arise.
The risk of leaving it on is that debug.log grows over time. If you leave it on, set up log rotation or use WPDT’s automatic log cleanup to manage file size.
If wp-config.php contains two definitions for the same constant, PHP uses the first one and ignores the second. You see a notice like:
PHP Notice: Constant WP_DEBUG already defined in /wp-config.php on line 92
Search the file for duplicate define('WP_DEBUG' lines. Remove the duplicate. Some hosting panels or security plugins add their own definitions — check the entire file.
The /* That's all, stop editing! */ comment is followed by code that loads WordPress. Constants defined after this line may not take effect because WordPress has already initialized.
Move your define() statements above that comment.
WP_DEBUG_LOG writes to a file. WP_DEBUG_DISPLAY shows in the browser. These are independent settings. Enabling WP_DEBUG_LOG does not show anything on screen. Enabling WP_DEBUG_DISPLAY does not write to a file.
If you want both, set both to true. If you want logging without browser output (the production setup), set WP_DEBUG_LOG to true and WP_DEBUG_DISPLAY to false.
Check these in order:
WP_DEBUG set to true? Without this, nothing is reported.WP_DEBUG_LOG set to true? Without this, reported errors are not written to a file.wp-content/ directory writable by PHP? Check file permissions — the directory needs to be writable (typically 0755) for WordPress to create debug.log.WP_DEBUG_DISPLAY is set to true. Change it to false:
define('WP_DEBUG_DISPLAY', false);
If you changed it but errors still show, check for a second definition of WP_DEBUG_DISPLAY later in the file. Also check whether a plugin is calling ini_set('display_errors', '1') — this overrides the constant.
You can also force display off at the PHP level by adding this to wp-config.php:
@ini_set('display_errors', 0);
WordPress needs write access to the wp-content/ directory (or whatever directory the log file lives in). If PHP cannot write to the directory, no log file is created and no errors are logged.
Check permissions:
ls -la wp-content/
The directory should be owned by the web server user (often www-data on Linux) or your hosting account user, with permissions 0755. The debug.log file, once created, should have permissions 0644.
If you are on shared hosting without shell access, use your hosting panel’s file manager to check and fix permissions.
Some hosting environments (Flywheel, certain managed hosts) make wp-config.php read-only. In this case, WPDT attempts automatic permission elevation — temporarily making the file writable, writing the change, and restoring the original permissions. If that fails, you need to edit the file through your host’s control panel or contact support.
Instead of the default wp-content/debug.log, you can write errors to any path by setting WP_DEBUG_LOG to a string:
define('WP_DEBUG_LOG', '/home/user/logs/wordpress-debug.log');
This is useful when:
WPDT supports custom paths. Set the path in Settings → File Paths or define the DBTK_LOG_PATH constant. See Custom Log Paths for details.
define('SCRIPT_DEBUG', true);
This constant tells WordPress to load the original, unminified versions of core JavaScript and CSS files instead of the minified versions. It is useful when you are debugging JavaScript errors that reference line numbers in minified files — the unminified versions have readable variable names and meaningful line numbers.
SCRIPT_DEBUG has no effect on plugin or theme files unless those plugins/themes explicitly check for it.
define('WP_DISABLE_FATAL_ERROR_HANDLER', true);
Since WordPress 5.2, fatal errors are caught by a built-in fatal error handler. Instead of a blank white screen, WordPress shows a “There has been a critical error” message and sends a recovery email to the admin.
Setting WP_DISABLE_FATAL_ERROR_HANDLER to true disables this handler. Fatal errors produce the classic white screen (or PHP’s default error output if display_errors is on). This is sometimes useful during development if the recovery mode handler is interfering with your debugging workflow, but it should not be enabled on production.
define('CONCATENATE_SCRIPTS', false);
WordPress concatenates admin scripts into fewer HTTP requests by default. Setting this to false loads each script individually, which makes it easier to identify which script is causing a JavaScript error. This is an admin-only setting and has no effect on the frontend.
define('SAVEQUERIES', true);
This stores every database query WordPress runs during a page load, along with the execution time and a backtrace of the calling code. The data is stored in $wpdb->queries and can be dumped for analysis.
Do not leave SAVEQUERIES enabled on production — it consumes significant memory on complex pages. Use it for targeted debugging sessions or use WPDT’s Database Monitor for a more practical approach. See How to Find Slow Database Queries.
| Manual (wp-config.php) | WPDT (UI/CLI) | |
|---|---|---|
| How to enable | Edit file, add define() lines | Toggle switch or wp dbtk debug on |
| How to disable | Edit file, change values to false | Toggle switch or wp dbtk debug off |
| Backup before changes | You handle it | Automatic backup |
| Works without wp-admin | Yes (via FTP/SSH) | Yes (via standalone viewer or WP-CLI) |
| Works without WordPress | Yes (editing a PHP file) | Viewer: yes. Admin UI: no. |
| Risk of typos | Yes (editing PHP by hand) | No (UI writes the constants) |
| GridPane compatibility | Manual: edit secure-debug.php | Automatic detection and handling |
| Hosting with read-only wp-config | Manual: contact host | Automatic permission elevation (when possible) |