Skip to content

How to turn on WordPress debug mode, read the log and turn it off

Put three lines in wp-config.php that set WP_DEBUG to true, WP_DEBUG_LOG to true and WP_DEBUG_DISPLAY to false. Errors then go to wp-content/debug.log and stay off the page. Read the newest lines, set WP_DEBUG back to false and delete the log.

By
WP Ministry
Published

In short

  • Debug mode makes WordPress report every PHP error, warning and notice. On a live site, send them to a file and keep them off the page.
  • The three lines replace the WP_DEBUG line already in wp-config.php, above the stop-editing line.
  • The log is wp-content/debug.log unless you give WP_DEBUG_LOG a path. Kept inside the website's folder, it can be read by anyone who knows its address.
  • A log line gives a time, a level, a message, a file and a line number. The folder in the file's path names the plugin or theme.
  • Fatal errors and parse errors stop a page. Warnings, notices and deprecations do not.
  • When you are done, set WP_DEBUG to false, remove the other two lines and delete the log.

Debug mode is a setting in wp-config.php that makes WordPress report every PHP error, warning and notice, along with its own notices about outdated code. To use it safely on a live site, add three lines: one turns it on, one writes the messages to a file, and one keeps them off the pages your visitors see.

Then load the page that misbehaves, read the newest lines of wp-content/debug.log, and turn debug mode off again. WordPress's documentation says its debug tools are meant for local and staging sites, not live ones. If you have a staging site that shows the same fault, work there. If the fault shows only on the live site, keep debug mode on for as long as the search takes and no longer.

Why errors must stay off the page

With WP_DEBUG on and nothing else set, WordPress prints each message into the HTML of the page that caused it. Visitors see raw error text in the middle of your site, and so does anyone looking for a way in. The PHP manual lists what such a message can give away: how the files on the server are organized, which database the site runs on, and how a page is built. The same manual says that showing errors is for development and should never be used on a system connected to the internet, and that a live site should log them instead.

That is what the other two lines are for. WP_DEBUG_LOG saves every message to a file. WP_DEBUG_DISPLAY, set to false, forces them off the page. Neither does anything unless WP_DEBUG is true.

Some errors never reach a page in any case. WordPress does not print errors into its answers to Ajax, REST API and XML-RPC requests, whatever the display setting. For a form that spins or a button that does nothing, the log is where the error is written.

Turn debug mode on in wp-config.php

  1. Step 1: Open wp-config.php

    It is in the folder WordPress is installed in. Open it in your host's file manager, or download it over SFTP and edit it in a plain text editor.

  2. Step 2: Find the WP_DEBUG line

    A standard file already has one: define( 'WP_DEBUG', false );. Search the file for WP_DEBUG.

  3. Step 3: Replace that line with these three

    wp-config.php
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
  4. Step 4: Save, then load the page that shows the fault

    The page should look as it did before, with no error text added to it. Check in a private browser window, as a visitor would see it.

  5. Step 5: Look for the log

    Open the wp-content folder. A file named debug.log appears the first time there is something to record.

Three things decide whether the lines work.

  • Replace, do not add. PHP sets a constant once, and its value cannot change afterwards. If the old WP_DEBUG line stays and a new one is added below it, the old one still decides.
  • Stay above the stop-editing line. If the file has no WP_DEBUG line, put the three above the comment that begins /* That's all, stop editing!. The lines after that comment load WordPress, and by then it has given every debug setting it did not find its default value.
  • No quotes around true and false. WordPress's documentation warns that 'false' in quotes is a piece of text, not a no, and counts as true.

With WP-CLI

bash
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw

Each command changes the line if the file has one, and adds it above the stop-editing line if not. WP-CLI answers each with a line that begins Success:. Keep --raw. It writes the value as it is; without it, WP-CLI writes a quoted string, which is the mistake described above. To see what a constant is set to now, run wp config get WP_DEBUG.

Where the log is, and who can read it

Unless you say otherwise, the log is wp-content/debug.log. That folder is part of the website, so the log has an address: https://example.com/wp-content/debug.log, with your own domain. Unless the server refuses the request, anyone who types that address can read the file. WordPress says so itself. Go to Tools, then Site Health: while the log is on, the Status tab lists "Your site is set to log errors to a potentially public file".

A log names the folders on your server and the plugins you run, and a plugin can write anything it likes there. So check before you go on. Open the log's address in a private window. If the text of the log appears, do one of the two things below.

Move the log out of the website's folder

WP_DEBUG_LOG also takes the full path of a file, in quotes, in place of true:

wp-config.php
define( 'WP_DEBUG_LOG', '/home/example/logs/wp-errors.log' );

Choose a folder that is not inside the one holding the website's files. Your host's file manager shows the full path. The folder has to exist already, and the web server has to be able to write in it. The file itself is made when the first message is recorded. With WP-CLI, leave --raw off here, because a path is a quoted string: wp config set WP_DEBUG_LOG /home/example/logs/wp-errors.log.

Site Health rates a log kept inside the WordPress folder as a critical issue, and one kept outside it as a recommended improvement.

Or have the server refuse the file

Keep a copy of .htaccess before you change it.

.htaccess

<Files "debug.log">
    Require all denied
</Files>
Apache reads this from .htaccess in the site's main folder. On nginx it goes inside the site's server block.

On nginx, if WordPress is installed in a subfolder, the path includes it, as in /blog/wp-content/debug.log. Load the log's address again. The server should now refuse the request and show none of the log. To undo the rule, remove the lines. If every page shows an error after you saved .htaccess, the server could not read a line in it: see how to fix the 500 internal server error.

How to read a log line

Note the time, then load the faulty page. Open the log and go to the end, where the newest lines are. A line looks like this:

text
[07-Oct-2026 14:03:22 UTC] PHP Warning:  Undefined variable $columns in /home/example/public_html/wp-content/plugins/example-gallery/includes/render.php on line 118

It has five parts.

  • The time, in brackets, with its time zone. WordPress sets PHP's clock to UTC, so expect UTC and not your local time.
  • The level, here PHP Warning. The next section says what each level means.
  • The message. What PHP objected to, in its own words.
  • The file. The full path of the code that was running. A path through wp-content/plugins/ followed by a folder name points at that plugin, here one called example-gallery. A path through wp-content/themes/ points at a theme.
  • The line number in that file. You will not need it. The plugin's author will.

Two other shapes turn up. A fatal error can be followed by a block headed Stack trace:, which lists the calls that led to it. Those lines belong to the error above them. When the error's own file is inside wp-includes or wp-admin, look down the trace for a path through wp-content/plugins/ or wp-content/themes/: that code made the call that failed. And a line with a time but no level was written on purpose by a plugin or theme, through PHP's error_log() function.

If you would rather not read the log line by line, paste the lines into the WordPress error message and debug.log decoder. It shows what each one means, which plugin or theme it points at, and what to do first. It reads them in your browser, and nothing is sent.

Which lines matter

The level says how serious a line is.

Level in the logWhat it meansDoes the page stop?
PHP Fatal errorAn error PHP could not recover from.Yes
PHP Parse errorPHP could not read a file as code, as with a missing bracket or semicolon.Yes
PHP WarningSomething went wrong, and PHP carried on.No
PHP NoticeSomething that may be a mistake, or may be normal.No
PHP DeprecatedCode that works today and will not in a future version.No

Start with the fatal errors and parse errors written at the time of the fault. One of those stands behind a blank page and behind "There has been a critical error on this website.", and can stand behind a 500 error. How to fix the WordPress white screen of death and how to fix the 500 internal server error take it from there. A line about memory has its own page: how to fix "Allowed memory size exhausted".

Expect far more lines than faults. With debug mode off, WordPress asks PHP to report only errors and warnings. With it on, PHP reports everything, and WordPress adds notices of its own when a plugin or theme uses a function, an argument or a file that WordPress has deprecated. Those notices and deprecations were happening all along, unrecorded. A long log is not a broken site.

Read warnings when their time matches the fault. If the lines around a fault name two plugins, how to find and fix a WordPress plugin conflict shows how to prove which one is the cause. If you would rather hand the log to someone, our one-time fix starts with a free diagnosis: you get a written cause and a fixed quote.

Turn it off and delete the log

  1. Step 1: Set WP_DEBUG back to false

    This one line switches debug mode off. Remove the WP_DEBUG_LOG and WP_DEBUG_DISPLAY lines as well. They do nothing while WP_DEBUG is false, and removing them leaves the file as it was.

    wp-config.php
    define( 'WP_DEBUG', false );
  2. Step 2: Keep the lines you need

    A plugin's author will want the lines about their plugin. Copy those out, and read them before you send them anywhere.

  3. Step 3: Delete the log

    Delete debug.log, or the file you named, from the server. Switching debug mode off stops new lines. It does not remove the old ones, and the file stays readable at its address.

  4. Step 4: Check Site Health

    Go to Tools, then Site Health. "Your site is not set to output debug information" is now among the passed tests.

With WP-CLI:

bash
wp config set WP_DEBUG false --raw
wp config delete WP_DEBUG_LOG
wp config delete WP_DEBUG_DISPLAY

Two more debug constants

You will see these beside the three above. Neither is needed to find a failing plugin.

  • SCRIPT_DEBUG. Set to true, it makes WordPress load the full "dev" versions of its own CSS and JavaScript files in place of the minified ones. It is for someone tracing a fault in those scripts.
  • SAVEQUERIES. Set to true, it saves every database query, with the time it took and the function that called it, for a developer or a debugging plugin to read. WordPress's documentation warns that it slows the site and should be off whenever you are not debugging.

If you cannot change wp-config.php

PHP has a log of its own, set by the server and not by WordPress. Its error_log setting names the file. Where none is named, PHP hands errors to the web server's error log. With debug mode off, WordPress still leaves errors and warnings reported, so on a server that logs PHP errors a fatal error is written down without any change from you.

Look for an error log in your hosting panel, or ask the host what it says at the time of the fault. How to fix the 500 internal server error has the words to use. While WP_DEBUG_LOG is on, WordPress points that same setting at its own log, so look there first.

What the log will not show

  • A fault in the browser. A script that fails in the visitor's browser never reaches PHP. The plugin conflict guide linked above shows how to read the browser's console.
  • A fault in the web server. A 500 error caused by a bad line in .htaccess belongs to the web server and is in its log, not this one.
  • A page sent from a cache. When a saved copy of a page is sent, the code at fault may not run, and nothing is written. Empty the cache and load the page again.

Common questions

Is it safe to turn on debug mode on a live site?

WordPress's documentation does not recommend it, and says the debug tools are for local testing and staging sites. When a fault shows only on the live site, treat debug mode as a short measure: display off, the log moved or refused by the server, and everything switched off and deleted when you have your answer.

I turned it on and there is no debug.log. Why?

The file is made only when there is something to write, so load the page that shows the fault first. If it still does not appear, check that the lines sit above the stop-editing line and that no older WP_DEBUG line comes before them. The folder may also be closed to the web server: a log file has to be writable by it. Give WP_DEBUG_LOG a path to a folder that is, or ask your host.

Debug mode is on, and the page still says only "There has been a critical error on this website." Where is the error?

In the log. Since version 5.2, WordPress catches a fatal error, shows visitors a message of its own in place of the page, and emails the site's administrator a link to recovery mode. Find the newest PHP Fatal error line, or use the link: how to fix the WordPress white screen of death explains both. A constant named WP_DISABLE_FATAL_ERROR_HANDLER switches the message off, and recovery mode with it, so leave it out of a live site.

The log is full of "PHP Deprecated" lines. Is the site broken?

No. A deprecation says the code will stop working in a future version, and it works today. The lines matter before an upgrade to a newer PHP version: update the plugin or theme they name, or send the lines to its author.

More on this subject

Quick Fix, done for you

Quick Fix is $49. One issue, one site, up to about an hour. No fix, no fee. 30-day warranty. It starts with a free diagnosis.