Key facts at a glance
WordPress debugging in 2026
Last updated
- What it is
WP_DEBUGis a constant inwp-config.phpthat turns on WordPress debug mode. Default is off, which is why a broken site shows a generic message instead of the real PHP error.- The safe production combo
WP_DEBUGtrue,WP_DEBUG_LOGtrue,WP_DEBUG_DISPLAYfalse. Errors get logged to a file but never shown to visitors.- Where the log lives
- By default
wp-content/debug.log. You can send it to a custom absolute path by settingWP_DEBUG_LOGto that path instead of true. - The one skill that matters
- Read the file path in each entry.
/plugins/name/means that plugin./themes/name/means the theme./wp-includes/usually means a plugin called core the wrong way. - The four severities
- Fatal breaks the site, fix now. Warning means a feature is broken, fix soon. Deprecated means update the plugin. Notice is usually safe to ignore. Find the most recent Fatal first.
- The security rule
- Never leave
WP_DEBUG_DISPLAYon in production, it leaks file paths to visitors and attackers. The defaultdebug.logalso sits at a guessable public URL, and Site Health flags logging to a potentially public file. Move it outside the web root or block access, and turn debugging off when you are done.
Source: the WordPress debugging documentation in the Advanced Administration handbook, the WordPress Site Health documentation, the WordPress wp-config reference, the php.net supported versions schedule, and our hands-on repairs. Get a quote in 60 seconds →
What WP_DEBUG is and why it comes first
When a WordPress site breaks, it almost never tells you why. You see There has been a critical error on this website, or a blank white page, or a feature that silently stopped working. Those are deliberately generic. By default WordPress runs with debug mode off, so it catches the underlying PHP error and replaces it with a safe, vague message rather than printing technical details to your visitors. That is correct behavior for a live site, but it is useless for fixing the problem, because the actual cause, the file and line that failed, is hidden.
Turning on WP_DEBUG with logging changes that. WordPress starts recording every PHP error to a log file, each entry stamped with the exact file path and line number where it happened. Suddenly the question is not which of your twenty plugins broke the site, it is a fact written in the log. This is why enabling the debug log is the first step in nearly every WordPress repair, and why so many fix guides, including ours, begin with it. It is the difference between guessing and knowing. Every minute spent deactivating plugins one by one is a minute you could have skipped by reading one line.
Crucially, all of this is controlled from wp-config.php, a file in your site root, not from the WordPress dashboard. So you can enable debugging even when you are completely locked out of wp-admin, which is exactly when you most need it. Edit the file over SFTP, SSH, or your host file manager, add a few lines, and the log starts capturing the truth.
Turn on debugging the safe way
The goal on a live site is to capture errors to a file while showing nothing to visitors. Three constants do that. Open wp-config.php and add the following above the line that reads /* That's all, stop editing! */. Placement matters, because constants added after that line are ignored.
// Turn on debug mode
define( 'WP_DEBUG', true );
// Log everything to wp-content/debug.log
define( 'WP_DEBUG_LOG', true );
// Do NOT show errors to visitors on the page
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );WP_DEBUG switches on debug mode. WP_DEBUG_LOG writes every error to the log file. WP_DEBUG_DISPLAY set to false, reinforced by the ini_set line, keeps those errors off the visible page so customers never see them. Save the file, then load the broken page once to generate a fresh entry. There are two more constants worth knowing: SCRIPT_DEBUG set to true makes WordPress load the unminified core CSS and JavaScript, useful when debugging an editor or front-end script issue, and SAVEQUERIES set to true records every database query for performance work, though it is heavy and should be left off normally.
Instead of true, set WP_DEBUG_LOG to an absolute path outside your public web root, for example define( 'WP_DEBUG_LOG', '/home/you/private/wp-errors.log' );. WordPress writes there instead of the default public location, so the log cannot be loaded in a browser.
How to read the debug log
Open wp-content/debug.log through your file manager, SFTP, or SSH. New entries are added at the bottom, so the most recent error is the last block in the file. You do not need to read PHP. You need to do two things: find the most recent PHP Fatal error, and read its file path.
A typical fatal looks like this, and the part that matters is the path at the end.
[25-Jun-2026 14:03:51 UTC] PHP Fatal error: Uncaught Error:
Call to undefined function some_plugin_helper() in
/var/www/html/wp-content/plugins/legacy-slider/init.php:214You can ignore the function name and the technical detail. The path /wp-content/plugins/legacy-slider/ names the culprit: a plugin called legacy-slider. That single fact tells you what to update, replace, or deactivate. The rule generalizes:
/wp-content/plugins/NAME/→ that plugin caused it. Update, replace, or deactivate it./wp-content/themes/NAME/→ your theme caused it. Switch to a default theme to confirm./wp-includes/or/wp-admin/→ WordPress core, usually a plugin calling a core function the wrong way.
Now the severity table tells you which entries to care about. Find the most recent Fatal first, since that is what took the site down. Treat the rest as context.
| Log entry starts with | What it means |
|---|---|
| PHP Fatal error: Uncaught Error ... | Site-breaking. WordPress stopped executing on this line. This is almost always the thing that took the site down. Read its file path and act on it first. |
| PHP Warning: ... | The site is up but a feature is broken or behaving wrong. Fix soon. Often a plugin doing something the current PHP or WordPress version no longer allows. |
| PHP Deprecated: ... | A plugin or theme is calling a function being removed from PHP or WordPress. Not fatal yet. A signal to update that plugin before a future version breaks it. |
| PHP Notice: ... | Usually minor, often an undefined variable. The log fills with these harmlessly. Safe to ignore while you focus on the Fatal error above. |
What the error points you to
Once the log has named the error, match it to the specific fix. These are the most common signatures and where each one leads.
PHP Fatal error: Uncaught Error in /wp-content/plugins/...A plugin took the site down. The path names which one. Update, replace, or deactivate it.
Fix plugin conflict →There has been a critical error on this website.The public face of a PHP fatal. The log and recovery email name the file behind it.
Fix critical error →Deprecated: Implicitly marking parameter ... nullablePHP 8.4 deprecations from an outdated plugin, often after a host forced the upgrade.
Fix PHP 8.4 breakage →Fatal error: Allowed memory size of X bytes exhaustedThe PHP memory limit was hit. Raise it the right way or fix the plugin leaking memory.
Fix memory exhaustion →The response is not a valid JSON responseThe block editor cannot save because the REST API is blocked or contaminated.
Fix publishing failed →HTTP Error 500 with a fatal in the server logA server-level failure past the WordPress handler. Often .htaccess or a resource limit.
Fix 500 error →Taming deprecation noise in 2026
In 2026 the debug log has a new problem: volume. PHP 8.4 made many older plugins emit Deprecated notices, and as hosts push sites onto 8.4, those notices can flood the log by the hundred, burying the one Fatal error you actually need. The fix is to keep logging real errors and warnings while filtering out only the deprecation level, so the signal is visible again.
Drop a small must-use plugin at wp-content/mu-plugins/quiet-deprecations.php that removes the deprecation level from error reporting. Must-use plugins load automatically and need no activation.
<?php
// Keep Fatal errors and Warnings, drop deprecation noise.
// Temporary, while you wait on plugin and theme updates.
error_reporting( error_reporting() & ~E_DEPRECATED & ~E_USER_DEPRECATED );This is a focus tool, not a fix. Quieting the deprecations makes the log readable, but the deprecations are still a warning that those plugins will break on a future PHP version. The real resolution is to update or replace the outdated plugins emitting them. If the deprecations are themselves what broke the site, see our PHP 8.4 fix.
Turn it off and protect the log
Debugging is a flashlight, not a fixture. WordPress documentation is explicit that the debug tools are meant for testing and staging, not to be left running on a live site indefinitely. Two real risks make this matter. If WP_DEBUG_DISPLAY is ever on, errors print to the page and expose file paths, plugin names, and server details that help an attacker map your site. And the default wp-content/debug.log sits at a predictable, browser-reachable URL, so the log itself can become public. WordPress Site Health flags exactly this, warning when a site is set to log errors to a potentially public file.
So once you have read what you needed, turn debugging back off by setting the constants to false, or remove the lines. If you must leave logging on for a while, either point WP_DEBUG_LOG at a path outside the web root, or block direct access to the default file at the server level.
# Apache: deny browser access to the debug log
<Files "debug.log">
Require all denied
</Files>The principle is simple: capture the errors for yourself, never for the public. A debug log left readable at a guessable URL has handed attackers a running commentary on your site internals.
DIY vs hand it off
Reading the log is a learnable skill, and for a clear single Fatal error you can often fix it yourself. When the log is noisy, the path is core, or the fix is risky, handing it off is faster. If the left column matches you can likely do this. If the right column matches, get help.
Realistic on your own
- ✓You can edit wp-config.php over SFTP or a file manager
- ✓The log shows one clear Fatal error with a plugin path
- ✓An update or a swap for that plugin is available
- ✓You can deactivate the named plugin to confirm the fix
- ✓You remember to turn debugging back off afterward
- ✓You have a recent backup before making changes
Hand it off, save the time
- ✗The log is flooded and you cannot find the real Fatal
- ✗The path points at core and the real cause is unclear
- ✗The fix means editing plugin or theme code on a live site
- ✗The offending plugin is custom or paid with no update
- ✗You cannot safely edit wp-config.php or reach the files
- ✗The site is down and you need it back now, not after learning
A real debug-log session
A composite from the diagnoses we run most weeks, with identifying details removed.
A small business site went down with the critical error message across every page. The owner was locked out of wp-admin too, so the recovery email had gone to an address they no longer used. They had spent an hour deactivating plugins at random through SFTP with no result, because they could not tell which one to blame.
We edited wp-config.php over SFTP to enable WP_DEBUG and WP_DEBUG_LOG with display off, then loaded the homepage once. The new entry at the bottom of wp-content/debug.log read PHP Fatal error: Uncaught Error ... in /wp-content/plugins/an-old-gallery/loader.php. The hundreds of Deprecated lines above it were noise from two other plugins on PHP 8.4. The path made the culprit unambiguous: a gallery plugin not updated in years.
We renamed the an-old-gallery plugin folder to deactivate it, and the site came straight back. We replaced it with a maintained gallery, confirmed the pages that used it, then set the debug constants back to false so nothing was left logging in public. Total time on the actual fix was minutes once the log named the file, against an hour of fruitless guessing before.
WordPress debug log FAQ
What is WP_DEBUG and why is it the first thing to enable when something breaks?
WP_DEBUG is a setting in your wp-config.php file that turns on WordPress debug mode. When it is off, which is the default, WordPress hides the underlying PHP errors and shows a generic message like the critical error page or a blank screen, so you cannot see what actually went wrong. When you turn WP_DEBUG on and pair it with logging, WordPress records the real errors, including the exact file and line that failed. That is why it is the first move for almost any WordPress problem: it converts a vague symptom into a specific, named cause. Instead of guessing which of your plugins broke the site, you read one line in a log that names the file. It is the single highest-leverage diagnostic step in WordPress.
How do I turn on debugging without showing errors to my visitors?
Use three constants together so errors are logged to a file but never displayed on the page. In wp-config.php, above the line that says that is all, stop editing, add WP_DEBUG set to true, WP_DEBUG_LOG set to true, and WP_DEBUG_DISPLAY set to false, plus an ini setting to force display off. WP_DEBUG turns on debug mode, WP_DEBUG_LOG writes everything to a log file, and WP_DEBUG_DISPLAY set to false keeps those errors out of the visible page so customers never see them. This combination is the safe way to debug a live site. It captures the real errors quietly in the background while your visitors keep seeing a normal site, which matters because the on-screen errors can leak file paths and other information you do not want public.
Where is the WordPress debug log and how do I read it?
By default the log is written to debug.log inside your wp-content directory, so the path is wp-content/debug.log. You can reach it through your hosting file manager, SFTP, or SSH. Open it and look at the most recent entries at the bottom. You do not need to understand the PHP. The one skill that matters is reading the file path in each entry. A path under wp-content/plugins/ followed by a plugin name tells you that plugin caused the error. A path under wp-content/themes/ points at your theme. A path under wp-includes/ points at WordPress core, which usually means a plugin called a core function the wrong way. That path is what turns a mystery into a specific plugin you can update, replace, or deactivate.
What do the different error types in the log mean?
There are four levels and they are not equally urgent. A PHP Fatal error is site-breaking: WordPress stopped executing, and this is the line that took your site down, so act on it first. A PHP Warning means the site is still up but a feature is misbehaving and should be fixed soon. A PHP Deprecated notice means a plugin or theme is calling a function that is being removed from PHP or WordPress, which is a signal to update that plugin before a future version breaks it. A PHP Notice is usually minor, often an undefined variable, and the log fills with these harmlessly. When you open the log, find the most recent Fatal error first, because that is almost always the thing you are trying to fix. The rest is context.
My debug log is flooded with Deprecated notices. Can I quiet them?
Yes, and in 2026 this is common because PHP 8.4 made many older plugins emit deprecation notices, which can bury the one Fatal error you actually need to see. The clean approach is to keep logging real warnings and errors while suppressing only the deprecation level. You can do that with a small must-use plugin that removes E_DEPRECATED from the error reporting level. That leaves Fatal errors and Warnings visible in the log while filtering out the deprecation noise. Do not solve this by turning logging off entirely, because then you lose the genuine errors too. Quieting deprecations is a focus tool, not a fix. The underlying answer is still to update or replace the outdated plugins that are emitting them.
Is it safe to leave WP_DEBUG on permanently?
No. WordPress documentation is explicit that debug tools are meant for testing and staging, not live sites left on indefinitely. Two risks matter. First, if WP_DEBUG_DISPLAY is ever on, errors print to the page and can reveal file paths, plugin names, and other details that help an attacker. Second, the default debug.log sits at a predictable, guessable URL inside wp-content, so anyone who knows the path may be able to read your error history, which can include sensitive information. WordPress Site Health even flags a site that is logging errors to a potentially public file. So enable debugging to capture the problem, then turn it off when you are done, and if you must leave logging on for a while, move the log outside the web root or block direct access to it.
How do I move the debug log somewhere private?
Instead of setting WP_DEBUG_LOG to true, set it to an absolute file path of your choosing, ideally outside the public web root so it cannot be reached from a browser. WordPress will write the log there instead of the default wp-content/debug.log. If you cannot place it outside the web root, the alternative is to block direct access to the default file with a server rule, for example denying requests to debug.log in your server configuration. Either way the goal is the same: capture the errors for yourself while making sure a visitor or a bot cannot simply load the log in a browser and read it. This is the difference between debugging responsibly and accidentally publishing your error history.
I cannot reach wp-admin at all. Can I still enable debugging?
Yes, and this is exactly when the log is most valuable. WP_DEBUG is set in wp-config.php, a file in your site root, not in the WordPress dashboard, so you can enable it even when you are locked out of wp-admin. Edit wp-config.php over SFTP, SSH, or your hosting file manager, add the debug constants, save, then reload the broken page once to generate a fresh entry in wp-content/debug.log. Open the log and read the most recent Fatal error and its file path. This is how we diagnose a fully down site: the dashboard is irrelevant because the answer is in a file you can reach without it. WordPress also emails a recovery link to the admin address when a fatal happens, which is a second way in.
Sources and further reading
Every claim on this page traces back to the WordPress debugging and Site Health documentation, the WordPress wp-config reference, or the php.net version schedule.