Something on your WordPress site breaks. A page goes blank, a form stops sending, a block editor won’t save — and the site tells you nothing. Just a white screen, or a vague “critical error” notice that names no plugin, no file, and no line number. So you start guessing: deactivate a plugin, refresh, guess again.
You don’t have to work that way. WordPress ships with a full debugging system baked into core, and it’s controlled by a handful of constants you drop into one file. Turn it on and the same broken page will hand you the exact file, function, and line that failed. The last white-screen we walked into was a client’s site right after a routine plugin update; the debug log pointed straight at a fatal “call to undefined function” from a plugin that assumed a newer version of PHP than the host was running. Two minutes of reading beat two hours of guessing.
This guide covers the debugging constants worth knowing, where to put them, how to read the log they produce, and the one setting you must never leave on for the public to see.
Why “It Just Broke” Is a Solvable Problem
By default, a production WordPress site hides its errors. That’s deliberate — you don’t want a PHP warning leaking a server path to a random visitor. But it also means that when something fails, the useful details are being generated and then thrown away. Debug mode simply catches them and puts them somewhere you can read.
There are really two audiences for an error. Visitors should never see one; they should get a clean page or a polite failure. You, the person fixing it, need the raw truth — the file, the line, the stack of what called what. WordPress lets you split those two by writing errors to a private log while keeping the front end clean. That single split is what turns “the site is broken” into “line 214 of that plugin is broken.”
A “white screen of death” or a generic critical-error email almost always has a precise cause waiting in the log. Debug mode is the difference between deactivating plugins one at a time hoping the symptom disappears, and reading the exact file and line number that threw the error. It usually turns an afternoon of guessing into a five-minute fix.
The One File That Controls It All
Every debugging switch lives in wp-config.php, the configuration file in your site’s root directory. You edit it over SFTP, through your host’s file manager, or from the command line. WordPress reads these constants early in the boot process, so they govern the whole request.
The single most important rule about editing this file: your constants have to go above the line that reads /* That's all, stop editing! Happy publishing. */. Anything you paste below that comment is ignored, because WordPress has already finished loading its settings by the time it gets there. This trips up more people than any other part of debugging, so it’s worth double-checking.
The master switch: WP_DEBUG
WP_DEBUG is the on/off toggle for the entire system, and it defaults to false. Set it to true and WordPress starts reporting PHP errors, warnings, and notices, plus its own deprecation warnings when a theme or plugin calls a function that’s on its way out.
define( 'WP_DEBUG', true );
On its own, this sends errors to wherever your PHP install is configured to put them, and — unless you change the next two settings — it also prints them right onto the page. That’s fine on a local or staging copy. It is not something you want a live audience to see, which is exactly what the logging and display constants are for.
Catch it quietly: WP_DEBUG_LOG
Set WP_DEBUG_LOG to true and WordPress appends every error to a file at wp-content/debug.log. Nothing shows on screen from this setting alone; the errors just accumulate in a file you can open whenever you like. Since WordPress 5.1 you can also give it a full file path instead of true, and the log writes there instead — handy for keeping the file outside a publicly reachable folder.
define( 'WP_DEBUG_LOG', true );
// or, to choose the location:
define( 'WP_DEBUG_LOG', '/home/you/private-logs/wp-errors.log' );
One catch worth knowing: WP_DEBUG_LOG only does anything while WP_DEBUG is also true. The log is a companion to the master switch, not a replacement for it.
Keep it off the front end: WP_DEBUG_DISPLAY
This is the setting that protects your visitors. WP_DEBUG_DISPLAY controls whether errors are printed into the HTML of the page, and it defaults to true. On a live site you want it false so that errors go to the log and nowhere else.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
That four-line block is the production-safe pattern: debugging is on, everything is logged, and nothing surfaces to the public. The @ini_set line is a belt-and-suspenders addition that tells PHP itself not to echo errors, in case a plugin or your host has flipped that on somewhere else.
Never leave WP_DEBUG displaying errors on a production site. A visible warning can reveal your server’s absolute file paths, plugin internals, and database structure — a genuine reconnaissance gift to an attacker. Debug on a live site, sure, but log quietly: WP_DEBUG_DISPLAY stays false, and you turn the whole thing back off once you’re done.
Two More Switches Developers Reach For
SCRIPT_DEBUG
WordPress ships minified versions of its core CSS and JavaScript for speed. When you’re chasing a bug in a script — or in something that hooks into one — that minification makes the code nearly unreadable. SCRIPT_DEBUG defaults to false; set it true and WordPress loads the full, un-minified “dev” versions of its bundled assets instead.
define( 'SCRIPT_DEBUG', true );
It only affects core’s own files, not your theme or third-party plugins, but when the problem is in the block editor or a core library, it makes the source legible again.
SAVEQUERIES
If a page is slow and you suspect the database, SAVEQUERIES tells WordPress to record every query it runs — along with the time each took and the function that fired it — into the $wpdb->queries array. It’s a precise way to find the one plugin issuing five hundred queries on your homepage.
define( 'SAVEQUERIES', true );
Because it stores every query in memory, it carries a real performance cost of its own. Turn it on to investigate, read what you need, and turn it back off. Leaving it running on a busy production site is the kind of thing that quietly makes the slowness you were investigating worse.
WP_DEBUG— master switch; enables error, warning, and deprecation reporting. Defaultfalse.WP_DEBUG_LOG— writes errors towp-content/debug.log(or a path you specify). NeedsWP_DEBUGon.WP_DEBUG_DISPLAY— shows errors in the page HTML. Setfalsein production.SCRIPT_DEBUG— loads un-minified core CSS/JS. Defaultfalse.SAVEQUERIES— records every DB query for profiling. Costs memory; use briefly.
Reading the Log Without Losing Your Mind
Once logging is on, reproduce the problem — load the broken page, submit the failing form — and then open wp-content/debug.log. Each entry carries a timestamp, an error type, a message, and a path. A typical fatal looks like this:
[23-Jul-2026 03:14:52 UTC] PHP Fatal error: Uncaught Error:
Call to undefined function acme_render_widget() in
/wp-content/plugins/acme-widgets/render.php:214
Read it from the file path backward. The line tells you the failing function, the file, and the exact line number — render.php at line 214, inside the acme-widgets plugin. That’s your suspect, no guesswork required. Fatal errors halt the request, so they’re what caused your white screen; warnings and notices don’t stop the page but often explain flaky, intermittent behavior.
Not every line is urgent. A live site with a few active plugins will log deprecation notices and minor warnings that have nothing to do with your problem. Scan for the word Fatal first, note the timestamp that matches when you reproduced the bug, and ignore the background noise. If the file is enormous, delete it, reproduce the issue once, and read the fresh, short log that results.
A safer default: move the log somewhere private
The default location, wp-content/debug.log, sits inside a folder your web server can serve. On many setups that file is reachable at yoursite.com/wp-content/debug.log by anyone who guesses the URL, and an error log can leak plenty about how your site is built. Either point WP_DEBUG_LOG at a path outside your web root, or block direct access to .log files at the server level. Cleaning up after yourself matters too: delete the log and switch debugging off when the investigation’s over.
Faster Iteration: WP-CLI and Query Monitor
Flip the switches from the command line
If you have shell access, WP-CLI edits wp-config.php for you without opening an editor. The --raw flag matters here — it writes an actual boolean instead of the string "true":
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw
When you’re finished, wp config set WP_DEBUG false --raw turns it all off again. It’s quick enough that leaving debug mode on “just in case” stops being tempting.
Query Monitor turns the log into a dashboard
For anything beyond reading a text file, Query Monitor is the tool most WordPress developers keep installed. It’s a free, GPL-licensed developer panel that surfaces database queries, PHP errors, hooks, HTTP API calls, and slow queries right in your admin bar — no log-diving required. It reads far better than a raw file, and it shows you which plugin or theme owns each query and error. Keep it on staging; there’s no reason to run it on a live production site.
Turning It Off Is Part of the Job
Debugging is a temporary state, not a permanent configuration. Once you’ve found and fixed the problem, set WP_DEBUG back to false (or clear it with WP-CLI), and delete any debug.log you generated. Leaving a site in debug mode is the most common security slip we see in otherwise well-run installs — a logging file quietly filling with paths and stack traces, sitting in a folder anyone can reach. Fix, verify, then flip it off.
Frequently Asked Questions
Next time your site breaks without explanation, don’t start guessing — turn on the log and let WordPress tell you exactly where it hurts. A few minutes with WP_DEBUG beats an afternoon of deactivating plugins one at a time.
Built by amplifi.studio — see also our guide to wp-config.php.