set_error_handler

Registers a user function to handle PHP errors instead of the built-in handler.

Signature
set_error_handler(?callable $callback, int $error_levels = E_ALL): ?callable
  • Added in PHP 4.0.1

Parameters

ParameterTypeDescription
$callback?callableThe handler, called as handler(int $errno, string $errstr, string $errfile, int $errline): bool. Returning false hands the error back to PHP's built-in handler; any other return value marks it handled. Pass null to reset to the built-in handler.
$error_levelsoptionalint= E_ALLBitmask of the error levels for which the callback should be invoked.

Return value

?callableThe previously defined error handler as a callable, or null if the built-in handler was active.

Errors

A TypeError is thrown if callback is not a valid callable and not null.

Changelog

  • PHP 8.0.0errcontext was removed and is no longer passed to user callbacks.
  • PHP 7.2.0errcontext became deprecated; declaring the parameter emits an E_DEPRECATED notice.

Fatal errors are out of reach: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR and E_COMPILE_WARNING never reach a user handler, and most E_STRICT-level diagnostics raised in the file where set_error_handler() itself is called are also missed. (php.net says "and most of E_STRICT raised in the file where set_error_handler() is called" — ordinary errors raised in that same file ARE handled, as this page's own runnable example demonstrates by catching a warning triggered a few lines below the set_error_handler() call.)

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Convert warnings from legacy functions into catchable ErrorException objects
  • Route every notice and deprecation into a structured application log
  • Fail a test suite the moment any deprecation notice is emitted

Frequently asked questions

Can set_error_handler catch fatal errors?

No. E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR and E_COMPILE_WARNING never reach a user handler. Use register_shutdown_function() with error_get_last() to detect them.

What is the difference between set_error_handler and set_exception_handler?

set_error_handler() handles PHP's classic error levels such as warnings and notices, while set_exception_handler() handles Throwable objects that escaped every try/catch. They are separate systems and most applications install both.

Does my error handler need to return true?

Returning false passes the error on to PHP's built-in handler so it is still printed and logged; returning true marks it fully handled and also prevents error_get_last() from seeing it.

More examples

Turn warnings into exceptions

The undefined array key raises a warning, the handler throws it as an ErrorException, and the catch block turns a silent notice into a controlled failure. getSeverity() returns the original E_WARNING value so you can still tell what kind of error it was.

Example · php
<?php
set_error_handler(function (int $no, string $str, string $file, int $line): bool {
    throw new ErrorException($str, 0, $no, $file, $line);
});

try {
    $config = [];
    echo $config['timeout'];
} catch (ErrorException $e) {
    echo 'converted: ', $e->getMessage(), "\n";
    echo 'severity:  ', $e->getSeverity(), "\n";
}

restore_error_handler();

Respect the @ operator

Inside the handler, error_reporting() returns a reduced mask for the suppressed call, so the first message prints as ignored and the second as reported. Without this check your handler would override every @ in the codebase.

Example · php
<?php
set_error_handler(function (int $no, string $msg): bool {
    if (error_reporting() === 0 || !(error_reporting() & $no)) {
        echo "ignored (suppressed): {$msg}\n";
        return true;
    }
    echo "reported: {$msg}\n";
    return true;
});

@trigger_error('quiet', E_USER_NOTICE);
trigger_error('loud', E_USER_NOTICE);
restore_error_handler();

Limit the handler to specific levels

The second argument narrows the handler to deprecation levels only, so the notice bypasses it entirely and falls through to PHP's normal handling. This is cleaner than checking the level inside the handler when you only care about one category.

Example · php
<?php
set_error_handler(
    fn(int $no, string $msg): bool => print("deprecation: {$msg}\n"),
    E_USER_DEPRECATED | E_DEPRECATED
);

trigger_error('old method used', E_USER_DEPRECATED);   // handled
@trigger_error('not a deprecation', E_USER_NOTICE);    // built-in handler
echo "done\n";

restore_error_handler();

Discussion

  • Be the first to comment on this lesson.