WordPress
WordPress debug.log: enable WP_DEBUG_LOG safely
Turn on WP_DEBUG_LOG for background debugging in WordPress 6.x - with production safety, quieter logs, WP-CLI tips, and when Query Monitor is better.
- WordPress
- debugging
- WP_DEBUG
- security

When developing WordPress sites, you sometimes need to see what is happening in the background without dumping debug output on the screen. debug.log is still my go-to for that - but turn it off on production unless you have a very good reason and tight file permissions.
This post covers enabling WP_DEBUG_LOG safely in WordPress 6.x, reducing plugin noise, logging your own values, and choosing between debug.log, Query Monitor, and the host’s error log.
Enable logging in wp-config.php
In WordPress 6.x the constants follow the same pattern:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
Errors and your own error_log() calls go to wp-content/debug.log. Keeping WP_DEBUG_DISPLAY false stops visitors from seeing PHP notices.
Optional refinements:
// Only log (do not redefine if already set by the host)
if ( ! defined( 'WP_DEBUG_LOG' ) ) {
define( 'WP_DEBUG_LOG', true );
}
Some hosts route PHP errors to their own panel. If debug.log stays empty, check the hosting error log first before assuming WordPress is silent.
Production warning: A writable debug.log in a web-accessible directory can leak paths, usernames, queries, and plugin internals. On live sites I prefer staging-only debugging, or logging via the host’s error log. After a hack investigation, delete old debug logs - they are a common place to leave sensitive traces. See WordPress security cleanup after a hack for the full recovery workflow.
Staging workflow that does not bite you
A sane pattern:
- Reproduce the bug on staging with the same PHP version and plugins.
- Enable
WP_DEBUG+WP_DEBUG_LOGonly there. - Reproduce once, capture the log, then disable debugging.
- Fix on staging, deploy the fix - not the debug settings - to production.
If you must debug production:
- Enable logging briefly
- Restrict access to
wp-content/debug.logat the server level if possible - Download and delete the log when finished
- Confirm
WP_DEBUGis false again
Filter out plugin noise
Third-party plugins and themes often flood the log with deprecations and notices. That makes real errors hard to find.
A small must-use plugin in wp-content/mu-plugins/ can narrow what gets logged:
<?php
/**
* Plugin Name: Quieter error reporting for investigations
*/
error_reporting( E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_USER_NOTICE & ~E_STRICT & ~E_NOTICE );
MU-plugins load automatically - WordPress must-use plugins documentation replaces the old Codex page.
Do not leave a “silence everything” MU-plugin in production forever. It can hide the exact fatals you need later.
Log your own variables
Use error_log() for values you care about:
error_log( '---- my_function ----' );
error_log( print_r( $dataarray, true ) );
Tips that save time:
- Prefix lines with a unique token so you can
grepthe log - Log the request URI or a correlation ID when possible
- Pair logging with a reproducible URL, admin action, or WP-CLI command so you are not tailing a 50MB file blind
Example with WP-CLI (on hosts that support it):
wp eval 'error_log("cli probe ok");'
tail -n 50 wp-content/debug.log
debug.log vs Query Monitor vs host logs
| Tool | Best for |
|---|---|
| debug.log | Cron, background jobs, fatals that kill output, CLI |
| Query Monitor | Logged-in browsing: queries, hooks, HTTP API, template parts |
| Host error log | PHP fatals when WordPress never bootstraps cleanly |
I often start with Query Monitor for “this admin page is broken,” and reach for debug.log when the failure is intermittent, cron-related, or invisible in the browser.
Log rotation and size
Left alone, debug.log grows forever. Large logs:
- Waste disk
- Slow simple
tail/ FTP downloads - Sometimes get truncated awkwardly by hosts
Rotate or delete regularly during investigations. Never commit debug.log to git. Add it to .gitignore on every project.
When debug.log is the wrong tool
- Front-end JavaScript - browser DevTools or
console.login a local build - REST API issues - Network tab, or log inside
rest_request_after_callbacks - Performance - Query Monitor, New Relic / host APM, or slow query logs - not
error_log()in hot paths - Email / SMTP - transaction logs or a mail logger plugin, not PHP notices
Remember to switch off
Before deploy (or after the investigation):
- Set
WP_DEBUG(and usuallyWP_DEBUG_LOG) to false - Remove temporary MU-plugins that change error reporting
- Delete
debug.logfrom production - Confirm file permissions are back to normal
Debugging left on by accident is both a performance and security footgun.
Need help chasing a stubborn WordPress bug or hardening a site after messy debugging? Contact me or see WordPress & WooCommerce development.
Frequently asked questions
Should I leave WP_DEBUG on in production?
No. Leave debugging off on live sites unless you are actively investigating a critical issue, with tight file permissions and a plan to turn it off again the same day.
Where is WordPress debug.log stored?
By default at wp-content/debug.log when WP_DEBUG_LOG is true. Confirm the path with your host if they customize logging.
When should I use Query Monitor instead of debug.log?
Use Query Monitor for request-level PHP notices, queries, hooks, and HTTP calls while you are logged in. Use debug.log for background jobs, cron, CLI, and issues that do not show in a normal page load.