PHP: How do you get error messages to display?
You call your script and get a blank page. No message, no hint, nothing. That is one of the most frustrating moments in PHP development, and the fix consists of exactly two settings.
The two settings
To get an error message to show up, both settings have to be right:
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);
?>
display_errors decides whether anything is output at all.
error_reporting decides which messages those are. If you only set one of
the two, you still see nothing, or only part of it.
What the blank page actually is
This is worth looking at closely. Take a script with two problems: an access to an array key that is not set, and a call to a method that does not exist.
With display_errors=Off, the typical setting on a production system:
Port: (nicht gesetzt)
Zugriff ohne ??:
(exit code: 255)
And with display_errors=On and error_reporting=E_ALL:
Port: (nicht gesetzt)
Zugriff ohne ??:
Warning: Undefined array key "port" in /buggy.php on line 8
Fatal error: Uncaught Error: Call to undefined method stdClass::machWas() in /buggy.php:11
Stack trace:
#0 {main}
thrown in /buggy.php on line 11
(exit code: 255)
The decisive part is the last line: in both cases the exit code is 255. The
script therefore fails in exactly the same way. The blank page is not a
different state from the error message, it is the same state without any
feedback. display_errors does not repair anything, it only makes visible what
happens anyway.
error_reporting filters independently
If you turn on display_errors but forget error_reporting, you may still see
only part of the picture. With E_ALL & ~E_WARNING the same script looks like
this:
Port: (nicht gesetzt)
Zugriff ohne ??:
Fatal error: Uncaught Error: Call to undefined method stdClass::machWas() in /buggy.php:11
Stack trace:
#0 {main}
thrown in /buggy.php on line 11
(exit code: 255)
The warning about the array key has gone, the fatal error has stayed. That is exactly why the two settings belong together.
On production it belongs in the log
display_errors=On is a bad idea on a publicly reachable server. Error messages
give away file paths, class names and sometimes credentials. The right setting
there is:
display_errors = Off
log_errors = On
error_log = /path/to/your/error.log
The same messages then land in a file, complete with a timestamp:
[28-Aug-2026 19:59:46 UTC] PHP Warning: Undefined array key "port" in /buggy.php on line 8
[28-Aug-2026 19:59:46 UTC] PHP Fatal error: Uncaught Error: Call to undefined method stdClass::machWas() in /buggy.php:11
Stack trace:
#0 {main}
thrown in /buggy.php on line 11
Why ini_set() sometimes does not help
A common stumbling block: with a parse error, ini_set() is of no use. A
syntax error is detected before even one line of your script runs, so the line
that is supposed to turn on display_errors never executes.
For that case you have to set the option in php.ini itself — or, during
development, pass it on the command line:
user@pc:~$ php -d display_errors=1 -d error_reporting=E_ALL script.php
Which php.ini applies anyway?
The second big source of confusion. You edit a php.ini and nothing happens,
because a completely different one is being loaded. You find out like this:
user@pc:~$ php --ini
In the official PHP Docker image that comes with a surprise:
Configuration File (php.ini) Path: "/usr/local/etc/php"
Loaded Configuration File: (none)
Scan for additional .ini files in: "/usr/local/etc/php/conf.d"
Loaded Configuration File: (none) — the image loads no php.ini at all.
All that sits there are the templates php.ini-development and
php.ini-production, one of which you have to copy into place. If you edit a
php.ini inside a container and wonder why nothing changes, this is usually the
reason.
Also bear in mind that PHP-FPM and the command line can use different configurations. So if you see nothing through the web server but everything on the command line, go and look at the FPM configuration.
Summary
display_errorscontrols whether,error_reportingcontrols what. Set both.- The blank page is the same failure as the message, just without any output.
- On production:
display_errors=Offandlog_errors=On. - For parse errors only
php.inior-don the command line helps. php --initells you which configuration is actually being loaded.
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).