Home › Blog › Article

WordPress Error Log Setup: Config, Privacy & Reviews

WordPress Error Log Setup: Config, Privacy & Reviews

Set up WordPress error logging by enabling WP_DEBUG in wp-config.php, writing to a protected file outside the web root, disabling display_errors so visitors never see stack traces, then rotating logs with logrotate and filtering recurring notices. You know it worked when debug entries land in your chosen file, the front end shows no PHP messages, disk use stays flat, and your review pass separates real fatals from deprecated noise.

Preparation: What You Need Before Touching Config

Confirm shell or SFTP access to the server and locate your WordPress root. As of 2026, supported managed hosts run PHP 8.2 or 8.3; check with php -v over SSH. Back up wp-config.php before edits. Note your site’s document root — often /var/www/html or /home/user/public_html. If you lack SSH, ask your host for a staging clone first. Teams offering Custom WordPress Development usually include this audit as step one, because misplaced debug files are a common source of data leaks.

Verify PHP and Paths

Run php -i | grep error_log to see the system default log path. Record it; you will override it later. On cPanel, the path may be /home/user/logs/php_error.log. Keep this value handy for comparison after your change.

Step Process: Configure, Lock Down, Rotate and Review

  1. Enable WP_DEBUG and write to a private file outside the web root.
  2. Force display_errors off in PHP so no error is ever rendered to visitors.
  3. Install logrotate rules to cap size and keep disk usage predictable.
  4. Filter deprecations and known notices so reviews surface real faults.
  5. Validate by triggering a controlled error and reading the log file.
  6. Roll back by reverting constants and restoring the previous config backup.

Configuring WP_DEBUG

Open wp-config.php in your WordPress root. Above the line /* That's all, stop editing! */ insert the debug block. Use absolute paths and set WP_DEBUG_DISPLAY to false. The example below writes to /var/www/private/wp-error.log, a directory not served by the web server.

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/var/www/private/wp-error.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
define( 'SCRIPT_DEBUG', false );

Get a Quote

Email + requirement + budget range — we reply with a quote within 24 hours.

Why this shape: WP_DEBUG turns on reporting, WP_DEBUG_LOG with a string path (not boolean true) sends output to your file instead of the default wp-content/debug.log, which is publicly reachable if permissions slip. Save the file. Then create the private directory: mkdir -p /var/www/private && chown www-data:www-data /var/www/private && chmod 700 /var/www/private. Adjust owner to your PHP-FPM user (e.g. nginx or php-fpm).

Common pitfall: using define( 'WP_DEBUG_LOG', true ); drops the file at wp-content/debug.log. Anyone guessing that URL reads your stack traces. Always use a full path. Verify with tail -f /var/www/private/wp-error.log and load a page that calls a missing function in a mu-plugin; you should see a timestamped entry. To roll back, comment out the defines and restore your backup copy.

Never Exposing Errors Publicly

Even with WP_DEBUG_DISPLAY false, a host-level php.ini may re-enable printing. Check with php -i | grep display_errors. If it returns On, set display_errors = Off in your pool config or .user.ini for CGI setups. For Apache with mod_php, add php_flag display_errors off to .htaccess in the root. For Nginx with PHP-FPM, edit the pool www.conf and set php_admin_flag[display_errors] = off.

Test exposure: request a page that triggers a fatal (temporarily rename a required class in a plugin). The browser must return a generic 500 or your theme’s 404 template, never a stack trace. Use curl -sI https://yoursite.com/broken-path | head -1 to confirm headers do not leak PHP details. Pitfall: some page builders print their own notices; keep a staging flag so production never shows them. Rollback: revert .htaccess or pool file from backup and reload PHP-FPM with systemctl reload php8.3-fpm.

Rotation and Disk Usage

A busy site can write hundreds of MB per day. Use logrotate, standard on Ubuntu 24.04 and RHEL 9 in 2026. Create /etc/logrotate.d/wordpress-error:

/var/www/private/wp-error.log {
    daily
    rotate 7
    size 50M
    compress
    delaycompress
    missingok
    notifempty
    create 600 www-data www-data
}

Why these values: size 50M with daily forces rotation when either condition hits; create 600 keeps the new file unreadable by other users. Test the rule with logrotate -d /etc/logrotate.d/wordpress-error for a dry run, then logrotate -f /etc/logrotate.d/wordpress-error to force one cycle. Verify with ls -lh /var/www/private/ — you should see wp-error.log.1.gz or similar. Pitfall: wrong owner in create stops PHP writing after rotation; the log silently stops. Rollback: remove the logrotate file and restart cron, then manually gzip the oversized log.

Separating Signal from Noise

WordPress core and plugins emit deprecations on PHP 8.2+ that bury real faults. During review, grep for the words that matter: grep -E 'Fatal|Parse|Uncaught' /var/www/private/wp-error.log | tail -20. Pipe through cut -d' ' -f1-3 | sort | uniq -c | sort -rn to count repeats. If one notice repeats 10k times, silence it at the source or add a targeted filter in a must-use plugin rather than turning debug off.

Use a weekly review habit: export unique fatals to a ticket, fix, then redeploy. For teams comparing vendors on related maintenance scope, see our WordPress SEO Issue Fix Guide which covers how logging fits into broader site health work. Pitfall: filtering too aggressively hides the one fatal you need. Always keep at least one raw rotated copy before pruning. Rollback: if a mu-plugin filter hides too much, delete the mu-plugin file and the raw log returns to full verbosity.

Verification: Prove It Worked

Trigger a safe error: add trigger_error( 'log-check-2026', E_USER_NOTICE ); to a staging footer, load the page, then grep log-check-2026 /var/www/private/wp-error.log. A hit confirms the pipeline. Next, visit the same page in a browser — no output should appear. Third, check disk: du -sh /var/www/private/ should stay under your rotate cap after a forced cycle. Finally, scan the log for Fatals only; if the list is short and actionable, your signal-to-noise tuning is done.

Rollback Plan

If the site breaks after config edits: restore wp-config.php from backup, set WP_DEBUG to false, remove the logrotate rule, and delete any stray debug.log in wp-content. Restart PHP-FPM and web server. Confirm the front end loads and no log file grows. Keep the backup copy for 30 days.

Frequently asked questions

Frequently asked questions

Where should the WordPress error log file live in 2026?

Put it outside the document root, such as /var/www/private/wp-error.log, owned by the PHP user with 600 permissions. Never leave it in wp-content where a browser can request it.

How do I stop errors showing to visitors?

Set WP_DEBUG_DISPLAY to false and force display_errors = Off in your PHP pool or .user.ini. Test with a controlled fatal and confirm the browser shows no stack trace.

Will logging slow my site down?

A small overhead per request is normal, but unrotated logs fill the disk. Use logrotate with a 50M cap and review weekly to keep performance and storage stable.

Action Checklist

  • Insert the WP_DEBUG block with an absolute private log path in wp-config.php.
  • Disable display_errors at PHP level and verify no trace renders publicly.
  • Add /etc/logrotate.d/wordpress-error and force one rotation to test.
  • Grep for Fatal and Uncaught weekly; silence only repeating noise.
  • Keep a 30-day backup of the original wp-config.php for instant rollback.

Need help hardening production logs and reviewing faults? Our engineers set up private logging, rotation and review pipelines. See our development services or browse the technical column for more guides. Start today.

References & further reading

Need WordPress Development?

Free proposal and quote within 24 hours — we serve clients worldwide.

QQ