Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

PHP Show All Errors: Why the Page Is Blank and How to Fix It

Sean

Platform Writer

Aug 14, 2026
7 min read

Two settings control this: error_reporting decides which errors are generated, and display_errors decides whether they are printed. You need both. And if setting them in your script changes nothing, that is because a fatal parse error happens before your script runs at all, which is the single most common reason people conclude PHP is hiding errors from them.

PHP Show All Errors: Why the Page Is Blank and How to Fix It

The blank white page is PHP’s least helpful behaviour, and the fix depends on which of three situations you are in. Getting the error visible is usually a two-minute job once you know which one applies.

Table of contents

The settings, and why both are needed

Put these at the very top of the entry point, before any other code.

<?php
error_reporting( E_ALL );
ini_set( 'display_errors', '1' );
ini_set( 'display_startup_errors', '1' );

error_reporting sets which categories are raised. E_ALL includes notices, warnings, deprecations, and fatals. display_errors decides whether they are written to the output. Setting only the first generates errors that go nowhere; setting only the second displays a subset.

display_startup_errors covers problems that occur during PHP’s own startup, before your code executes, which are otherwise invisible.

The alternative that also works and is easier to remember:

error_reporting( -1 );   // every current and future error level

A note on E_ALL across versions: it has meant different things historically, since E_STRICT was separate before PHP 5.4 and folded in afterwards, and E_STRICT itself was deprecated in PHP 8. On any supported version today, E_ALL is genuinely everything and the older workarounds combining constants are unnecessary.

Why setting them in the script does nothing

This is the case that sends people in circles. You add the lines, reload, and still get a blank page.

The reason is that a parse error is detected when the file is compiled, before any line of it executes. Your error_reporting call never runs, so it cannot affect the reporting of the error that prevented it from running.

The same applies to an error in a file included from the top of your script: the include is processed before your settings take effect if the include is above them.

Three ways out. The best is to check the syntax directly, which requires no configuration at all.

php -l suspect-file.php
# PHP Parse error: syntax error, unexpected '}' in suspect-file.php on line 42

# Check everything at once.
find . -name '*.php' -exec php -l {} \; | grep -v 'No syntax errors'

The second is to set the values in php.ini, which applies before compilation of anything. The third is the wrapper trick: a small file that enables display and then includes the broken one, so the settings are active when the problematic file is compiled.

<?php
// debug.php -- request this instead of the broken file.
error_reporting( E_ALL );
ini_set( 'display_errors', '1' );
include 'broken-file.php';

Setting it properly by environment

For development, set it in php.ini so it applies to everything, including files with parse errors.

; Development values.
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
error_log = /var/log/php/error.log

Find which file is actually being read, since a machine can easily have several and edit the wrong one.

php --ini
php -i | grep -E 'error_reporting|display_errors|error_log'

# The web server's PHP is often a different SAPI with a different ini.
# Check with a phpinfo() page on a development site, never in production.

That last caveat matters. The CLI and the web server frequently use different configuration files, so a setting confirmed at the command line may not apply to the site at all. That is a genuinely common source of confusion.

Per-directory overrides are also available without editing php.ini, through .htaccess on Apache with mod_php, or a user.ini file on many shared hosts.

; .user.ini in the document root
display_errors = On
error_reporting = E_ALL

Production: log, never display

Displaying errors in production is a security problem rather than a style preference. PHP error messages routinely contain absolute file paths, database names, table names, query fragments, and occasionally credentials from a connection string.

; Production values.
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL
error_log = /var/log/php/error.log

Note that error_reporting stays at E_ALL. You want everything recorded; you just do not want it on the page. Lowering the reporting level in production means the log is missing exactly the deprecation warnings that will become fatal errors at the next PHP upgrade.

Give users something useful instead by handling errors yourself.

set_exception_handler( function ( $e ) {
    error_log( sprintf(
        '[%s] %s in %s:%d',
        get_class( $e ), $e->getMessage(), $e->getFile(), $e->getLine()
    ) );
    http_response_code( 500 );
    echo 'Something went wrong. Reference: ' . uniqid();
} );

// Convert warnings and notices into exceptions so they cannot be ignored.
set_error_handler( function ( $severity, $message, $file, $line ) {
    if ( ! ( error_reporting() & $severity ) ) {
        return false;
    }
    throw new ErrorException( $message, 0, $severity, $file, $line );
} );

That second handler is a genuinely good habit. Turning warnings into exceptions means a notice about an undefined array key becomes a caught, logged failure instead of a null that propagates silently into your data.

The remaining blank-page causes

If display is on, the log is empty, and the page is still blank, work through these.

  • The error log is full or unwritable. PHP silently discards messages when it cannot write, and a 2GB log file on a full disk produces exactly this. Check the path exists and is writable by the web server user.
  • A fatal error inside an output buffer. If the buffer is discarded rather than flushed, the error goes with it.
  • The memory limit was exceeded. This produces a fatal error that should be logged, but a process killed by the operating system’s out-of-memory killer leaves nothing behind. Check dmesg.
  • The process hit max_execution_time and was terminated mid-request.
  • An opcode cache is serving a stale compiled version of a file you have since fixed. Restart PHP-FPM to clear it.
  • The web server, not PHP, is producing the blank response. Check the server error log as well, which is a different file.

The unwritable log case deserves the emphasis it gets, because it produces the most confusing version of this problem: errors are being generated correctly and going nowhere, so every change you make appears to have no effect.

How this fits the rest of the stack

The reason production debugging becomes archaeology is that the error log lives on a server and nobody knows which deploy introduced the problem. Keeping runtime logs alongside the build log for each deploy makes both questions answerable from the same place, and a rollback available when the answer is the last release. The RunxBuild hosting calculator shows the service and its managed database as separate line items.

Useful related references:

FAQ

Why is my PHP page blank with no error?

Most often a parse error, which happens at compile time before your error_reporting call executes. Run php -l on the file to see it. Failing that, check whether the error log is writable, since PHP discards messages silently when it cannot write.

What is the difference between error_reporting and display_errors?

error_reporting decides which error categories are raised. display_errors decides whether they are printed to the output. You need both to see errors on the page, and in production you want the first at E_ALL and the second off.

Should I show PHP errors in production?

No. Error messages leak file paths, database names, and query fragments. Set display_errors off, keep error_reporting at E_ALL, log to a file, and show users a generic message with a reference identifier.

Why does ini_set display_errors not work?

Either a parse error occurred before the line ran, or the directive was set after output had already started. For parse errors, set the value in php.ini or use php -l instead.

Where does PHP write its error log?

Wherever error_log points in the active php.ini, which you can find with php —ini. Note that the CLI and the web server often use different configuration files, so confirm from the web context rather than the terminal.

#PHP Errors#display_errors#error_reporting#PHP Debugging#White Screen