PHP Error Reporting: Enable, Display, and Log Errors

PHP error reporting controls which errors are shown, logged, or silently ignored. Configuring it correctly is essential during development, where you want full visibility, and on production servers, where errors should be logged but never displayed to users.
This guide explains how to configure PHP error reporting using php.ini, the error_reporting() function, and .htaccess. If you are not sure which PHP version is active, first check it with the PHP version guide
.
Quick Reference
For a printable quick reference, see the PHP cheatsheet .
| Task | Setting / Command |
|---|---|
| Enable all errors in php.ini | error_reporting = E_ALL |
| Display errors on screen | display_errors = On |
| Hide errors from users (production) | display_errors = Off |
| Log errors to a file | log_errors = On |
| Set custom log file | error_log = /var/log/php/error.log |
| Enable all errors at runtime | error_reporting(E_ALL); |
| Suppress all errors at runtime | error_reporting(0); |
| Set errors per directory on PHP-FPM | .user.ini in the web root |
| Pin error settings for an FPM pool | php_admin_value[error_log] |
PHP Error Levels
PHP categorizes errors into levels. Each level has a name (constant) and a numeric value. You can combine levels using bitwise operators to control exactly which errors are reported.
The most commonly used levels are:
E_ERROR- fatal errors that stop script execution (undefined function, missing module)E_WARNING- non-fatal errors that allow execution to continue (wrong function argument, missing include)E_PARSE- syntax errors detected at parse time; always stop executionE_NOTICE- runtime notices for possible issues; many conditions that once raised notices, including undefined variables, raiseE_WARNINGin PHP 8E_DEPRECATED- warnings about features that will be removed in future PHP versionsE_ALL- all errors and warnings; recommended during development
Two details changed in PHP 8.4. The E_STRICT level is deprecated and no longer used, and the value of E_ALL dropped from 32767 to 30719 because E_STRICT was removed from it. Older tutorials often recommend E_ALL & ~E_STRICT, which on current PHP masks a level that E_ALL no longer contains and therefore does nothing.
For a full list of error constants, see the PHP error constants documentation .
Configure Error Reporting in php.ini
The php.ini file is the main configuration file for PHP. Changes here apply globally to all PHP scripts that use that configuration file. After editing it, reload the process that runs PHP: Apache when using mod_php, or PHP-FPM when using FPM. CLI commands read php.ini each time they start.
To find the location of your active php.ini file, run:
php --iniEnable Error Reporting
Open php.ini and set the following directives:
; Report all errors
error_reporting = E_ALL
; Display errors on the page (development only)
display_errors = On
; Display startup sequence errors
display_startup_errors = Ondisplay_errors on a production server. Displaying error messages to users exposes file paths, database credentials, and application logic that can be exploited.Log Errors to a File
To write errors to a log file instead of displaying them, set:
; Disable displaying errors
display_errors = Off
; Enable error logging
log_errors = On
; Set the path to the log file
error_log = /var/log/php/error.logMake sure the directory exists and is writable by the web server user. To create the directory:
sudo mkdir -p /var/log/php
sudo chown www-data:www-data /var/log/phpRecommended Development Configuration
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
error_log = /var/log/php/error.logRecommended Production Configuration
error_reporting = E_ALL & ~E_DEPRECATED
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.logThis reports all errors except deprecation notices and logs every selected error without displaying anything to users.
Configure Error Reporting at Runtime
You can override php.ini settings within a PHP script using the error_reporting() function and ini_set(). Runtime changes apply only to the current script.
To enable all errors at the top of a script:
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);To report all errors except notices:
<?php
error_reporting(E_ALL & ~E_NOTICE);To suppress all error output (not recommended for debugging):
<?php
error_reporting(0);Runtime configuration is useful during development when you do not have access to php.ini, but it should not replace proper server-level configuration on production systems.
Configure Error Reporting in .htaccess
If you are on a shared hosting environment without access to php.ini, you can configure PHP error reporting via .htaccess (when PHP runs as an Apache module):
php_flag display_errors On
php_value error_reporting -1
php_flag log_errors On
php_value error_log /var/log/php/error.logUsing -1 for error_reporting enables all possible errors, including those added in future PHP versions.
.htaccess directives only work when PHP runs as an Apache module (mod_php). They have no effect with PHP-FPM.Configure Error Reporting with .user.ini
Most current hosting runs PHP through PHP-FPM or FastCGI rather than as an Apache module, which is why the .htaccess directives above are so often ignored. Those SAPIs read a per-directory file named .user.ini instead, and it gives you the same per-site control without access to the main php.ini.
Create the file in the directory you want to configure, which on a typical shared host is the web root:
error_reporting = E_ALL
display_errors = Off
log_errors = On
error_log = /home/user/logs/php-errors.logPHP scans for .user.ini starting in the directory of the requested script and works upward to the document root, so a single file in the web root covers the whole site. Only directives with a changeable mode of INI_ALL, INI_PERDIR, or INI_USER are accepted there, which covers all four settings above.
Changes do not take effect immediately. PHP caches the parsed file for the number of seconds set by user_ini.cache_ttl, which defaults to 300. If an edit appears to have been ignored, wait five minutes and reload the page before assuming the file is in the wrong directory.
Configure Error Reporting in the PHP-FPM Pool
On a server you administer, the pool configuration is the right place to pin error handling for a site. On Ubuntu and Debian, the pool file is /etc/php/<version>/fpm/pool.d/www.conf, such as /etc/php/8.5/fpm/pool.d/www.conf on Ubuntu 26.04 or /etc/php/8.4/fpm/pool.d/www.conf on Debian 13. Fedora, RHEL, and derivatives use /etc/php-fpm.d/www.conf.
The following example reuses the /var/log/php directory created earlier in this guide:
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php/error.log
php_admin_flag[display_errors] = offFedora and RHEL create /var/log/php-fpm with the PHP-FPM package, so you can use the packaged /var/log/php-fpm/www-error.log path there. Whichever path you choose must be writable by the pool user.
The php_admin_value and php_admin_flag directives differ from php_value and php_flag in one way that matters here: a script cannot override them with ini_set(). That makes them the right choice for display_errors on a production pool, where an application should not be able to switch error output back on for itself.
Reload the service after editing the pool file. Ubuntu and Debian use a versioned unit. For example, Ubuntu 26.04 uses:
sudo systemctl reload php8.5-fpmDebian 13 uses php8.4-fpm. Fedora, RHEL, and derivatives use the unversioned unit:
sudo systemctl reload php-fpmView PHP Error Logs
Once log_errors is enabled, errors are written to the file specified by error_log. To monitor the log in real time, use the tail -f
command:
sudo tail -f /var/log/php/error.logWhen error_log is not set, PHP hands the message to the error logger of the active SAPI, so where it lands depends on how PHP is running:
- Apache with
mod_php: the Apache error log, at/var/log/apache2/error.logon Ubuntu and Debian or/var/log/httpd/error_logon Fedora and RHEL. - PHP-FPM: the main FPM log configured by the global
error_logdirective inphp-fpm.conf. Common package defaults are/var/log/php<version>-fpm.logon Ubuntu and Debian and/var/log/php-fpm/error.logon Fedora and RHEL. - CLI: standard error, so the message appears in the terminal that ran the script.
The FPM pool setting catch_workers_output does not control messages produced by PHP’s log_errors directive. It only redirects output that worker processes or extensions write directly to their standard output and error streams. Normal PHP errors still go to the configured PHP log or, when error_log is unset, to the main FPM log.
Nginx does not execute PHP itself. PHP errors normally go to the PHP or FPM log, but messages that FPM sends over the FastCGI error stream can appear in /var/log/nginx/error.log as FastCGI sent in stderr. This can happen when PHP cannot open its configured log file, so check both logs when the expected PHP log remains empty. Our Nginx log files guide
covers what the Nginx log contains, and the 500 Internal Server Error guide
traces failed requests across both services.
For related service commands, see how to start, stop, or restart Apache and how to start, stop, or restart Nginx .
Troubleshooting
Errors are not displayed even with display_errors = On
Confirm you are editing the correct php.ini file. Run php --ini or call phpinfo() in a script to see which configuration file is loaded and the current value of display_errors.
Changes to php.ini have no effect
Reload the process that runs PHP after editing php.ini. For Apache with mod_php, run sudo systemctl reload apache2 on Ubuntu or Debian, or reload httpd on Fedora or RHEL. With PHP-FPM, reload its service, such as php8.5-fpm on Ubuntu 26.04, php8.4-fpm on Debian 13, or php-fpm on Fedora and RHEL. Nginx does not need a reload because it does not read php.ini.
No errors appear in the log file
Check that the log file path is writable by the PHP process user, and that log_errors = On is set in the active php.ini. Under PHP-FPM, inspect the main FPM log when error_log is unset. The global error_log directive in php-fpm.conf shows that log’s location.
Changes to .user.ini are ignored
PHP caches the file for user_ini.cache_ttl seconds, which defaults to 300. Give the cache time to expire before troubleshooting further. Also confirm that PHP runs under FPM or FastCGI, because mod_php does not read .user.ini at all.
ini_set('display_errors', '1') has no effect
Fatal parse errors (E_PARSE) occur before any PHP code runs, so ini_set() cannot catch them. Enable display_errors in php.ini or .htaccess to see parse errors.
Error suppression operator @ hides errors
PHP’s @ prefix suppresses errors for a single expression. If errors from a specific function are missing from logs, check whether the call is prefixed with @.
FAQ
What is the difference between display_errors and log_errors?display_errors controls whether errors are output directly to the browser or CLI. log_errors controls whether errors are written to the error log file. On production, always set display_errors = Off and log_errors = On.
Which error_reporting level should I use?
Use E_ALL during development to catch every possible issue. On production, use E_ALL & ~E_DEPRECATED to log serious errors while suppressing deprecation notices that do not require immediate action.
How do I check the current error reporting level?
Call error_reporting() with no arguments: it returns the current bitmask as an integer. You can also check it in the output of phpinfo().
Can I log errors to a database instead of a file?
Not directly via php.ini. Use a custom error handler registered with set_error_handler() and set_exception_handler() to send errors to a database, email, or external logging service.
Why do PHP errors not appear in the Nginx error log?
Nginx does not execute PHP, so PHP warnings normally go to the log configured by PHP or PHP-FPM. Messages that FPM sends through the FastCGI error stream can still appear in the Nginx error log as FastCGI sent in stderr, especially when PHP cannot write to its configured log. Check the PHP or FPM log first, then inspect the Nginx error log for FastCGI messages.
Where is php.ini located?
Run php --ini from the command line or add <?php phpinfo(); ?> to a script and load it in a browser. The “Loaded Configuration File” row shows the active path. Common locations are /etc/php/8.x/cli/php.ini (CLI) and /etc/php/8.x/apache2/php.ini (Apache).
Conclusion
During development, set error_reporting = E_ALL and display_errors = On in php.ini to see all errors immediately. On production, set display_errors = Off and log_errors = On to log errors silently without exposing details to users.
Make changes in php.ini for permanent server-wide configuration, use error_reporting() and ini_set() for per-script overrides, and reach for .user.ini on shared hosting without php.ini access, or .htaccess when the host still runs PHP as an Apache module.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page