What Are Common PHP Error Types? Warnings, Notices & Fatal Errors

Errors are an intrinsic part of software development. Sometimes you’ll find parts of your code don’t work as expected, instead triggering an error message that can be confusing to understand. Yet it’s important to recognize the meaning of different errors so you can effectively debug problems, pinpoint their sources, and maintain good code quality.

In this article, we’ll compile a list of some of the most common errors encountered by PHP developers. We’ll explain each error, show sample code that could cause it, and share tips on how to debug and prevent different PHP error types. Let’s begin!

Understanding PHP Error Levels

PHP reports an error whenever a code problem is found during runtime. Each error is assigned one of several levels, depending on its type and severity. Some of these levels mean your PHP application doesn’t run and must be urgently fixed, whereas other levels can be safely ignored.

Fatal Errors

Fatal errors (E_ERROR) are critical problems that PHP can’t automatically recover from, such as calling an undefined function. Your script will immediately exit when the error is triggered.

function foobar() : void {
    // ...
}

// PHP Fatal error:  Uncaught Error: Call to undefined function demo()
demo();

Parse Errors

Parse errors (E_PARSE) occur when PHP fails to parse the code in a script used by your application. They’re caused by typos that result in incorrect syntax. Parse errors have even higher priority than fatal errors—PHP will immediately exit, without running your script.

// PHP Parse error:  Unmatched '}'
// (Missing opening brace '{' after 'void' in the function signature)
function foobar() : void
    // ...
}

Warnings

Warnings (E_WARNING) are triggered when your code does something unexpected that’s likely to lead to an error, such as reading from an array key that doesn’t exist. Although warnings don’t necessarily mean your code is broken, you’re breaking best practices and may encounter issues in the future. Warnings do not halt PHP execution.

$arr = ["a", "b", "c"];

// PHP Warning:  Undefined array key 3
echo $arr[3];

Notices

Notices (E_NOTICE) were historically emitted for minor problems that are less urgent than warnings, such as accessing an undefined variable. However, the PHP 8.x release cycle has promoted the most common notices into warnings in recognition that they’re still likely to cause problems in your program. There are now few notices remaining and it’s best to treat them similarly to warnings.

Deprecated Errors

Deprecated errors (E_DEPRECATED) trigger when you run code that won’t work in a future PHP version, such as calling a function that’s planned to be removed. You don’t need to fix these errors immediately, but they’ll have to be dealt with before you upgrade to the next major PHP release.

Setting the PHP Error Reporting Level

You can configure which error levels are reported by calling the error_reporting() function or setting the error_reporting config value in your php.ini file. The value must be an integer that’s calculated as a bitmask of the PHP error level constants discussed above.

// Report all errors except Notices and Deprecations
error_reporting(E_ALL & E_NOTICE & E_DEPRECATED);

It’s common practice to reduce PHP’s error reporting level in production environments. This helps stop your logs becoming too noisy. However, it’s best to have all errors reported during development so you can easily find and fix possible issues with your code. Notices and deprecations don’t usually require urgent attention, but you should still be aware that they’re being emitted.

Errors vs Exceptions

PHP has two different error handling mechanisms: errors and exceptions. The error types discussed above implement a legacy style of procedural error handling that can only be caught by registering a custom error handler.

Exceptions offer a modern object-oriented error handling strategy. You can throw exception objects in your code, then use a try/catch code block to recover from the problem. You should prefer throwing exceptions over triggering errors because this provides more control. Recent PHP releases have been gradually migrating historic error types into new exceptions.

It’s possible to bridge the gap between errors and exceptions by registering a custom error handler that catches errors and throws a new ErrorException instance. The ErrorException class is a special type of exception that represents a previously caught error. It allows you to use try/catch constructs to deal with fatal, warning, notice, and deprecated errors emitted in your code.

// Register an error handler that converts errors to ErrorException exceptions
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline, array $errcontext) : bool {

    // Abort if the error isn't included in the configured error reporting level
    if (!(error_reporting() & $errno)) {
        return;
    }

    throw new \ErrorException(
        message: $errstr,
        code: 0,
        severity: $errno,
        filename: $errfile,
        line: $errline
    );

});

Some of the PHP errors we’ll look at below are true errors, whereas others are actually thrown exceptions.

Debugging Common PHP Errors

Now we’ve discussed PHP’s built-in error types, let’s look at some of the most regularly seen real-world errors. This isn’t an exhaustive list of errors you could encounter, but it should give you an effective starting point for diagnosing common problems.

Note: All the examples in this guide have been tested on PHP 8.4, the newest PHP feature release at the time of writing. Results may vary when using other PHP versions.

1. Undefined Variable

Undefined variable warnings are emitted when you use a variable that doesn’t exist in your code’s scope. It’s often caused by code similar to the following:

if (file_exists("/demo")) {
	$demo = "file";
}

// PHP Warning:  Undefined variable $demo
echo $demo;

In the example, the $demo variable is only defined if the file_exists("/demo") function returns true.

You can fix this error by making sure the variable is always defined before it’s first used:

$demo = "";

if (file_exists("/demo")) {
    $demo = "file";
}

echo $demo;

2. Cannot Use Object as Array

Cannot use object of type ... as array errors mean that you’ve tried to use an instance of a class as an array. It’s easy to make this mistake when you’re refactoring older applications that used to store data in associative arrays, but which now use classes instead.

class User {

    public function __construct(
        public readonly string $Username,
        public readonly bool $Active=true) {}

}

$myUser = new User("demo");

// PHP Fatal error:  Uncaught Error: Cannot use object of type User as array
echo ($myUser["Active"] ? "Active" : "Inactive");

In this example, although the User class has a property called Active, it can’t be accessed using array syntax. This is a fatal error so it will halt your application. Fortunately, it’s easy to fix by switching to the correct -> object access syntax:

class User {

    public function __construct(
        public readonly string $Username,
        public readonly bool $Active=true) {}

}

$myUser = new User("demo");

echo ($myUser -> Active ? "Active" : "Inactive");

3. Cannot Modify Header Information

The Cannot modify header information – headers already sent warning is a common frustration when you’re manually assembling HTTP responses. It occurs when you try to set a response header after you’ve already emitted some body data:

echo "Hello World!";

// PHP Warning:  Cannot modify header information - headers already sent
header("Demo-Header: foobar");

The problem is that HTTP responses require their headers to be sent ahead of their body content. PHP’s echo statement writes to the body, so in this example the headers have already been closed and sent before the header() function is called. To fix the issue, you should reorder your script so HTTP response headers are always sent before any body content:

header("Demo-Header: foobar");

echo "Hello World!";

4. Undefined Array Key

Undefined array key warnings are some of the most commonly encountered PHP errors. They occur when you try to access an array index that isn’t actually set:

$list = ["a", "b", "c"];

// PHP Warning:  Undefined array key 3
echo $list[3];

$assoc = ["a" => "x", "b" => "y", "c" => "z"];

// PHP Warning:  Undefined array key "d"
echo $assoc["d"];

To prevent this error from occurring, you must check that array indexes are defined before you access them. You can use isset(), array_key_exists(), or the null coalescing (??) operator:

$list = ["a", "b", "c"];

if (isset($list[3])) {
    echo $list[3];
}

$assoc = ["a" => "x", "b" => "y", "c" => "z"];

if (array_key_exists("d", $assoc)) {
    echo $assoc["d"];
}

// No warning even if $assoc["d"] is not set
echo ($assoc["d"] ?? "not set");

5. TypeError

PHP throws a TypeError exception whenever a type mismatch occurs. Common causes include passing an incorrect value to a function or returning an incorrect value from one:

declare(strict_types=1);

function sum(int $a, int $b) : int {
    return ($a + $b);
}

// PHP Fatal error:  Uncaught TypeError: sum(): Argument #2 ($b) must be of type int, string given
echo sum(10, "5");

Debug this error by checking the value types assigned to each of your variables. Types must be compatible with the typehints you’ve placed on each function, class, or interface.

declare(strict_types=1);

function sum(int $a, int $b) : int {
    return ($a + $b);
}

// Works OK — both values are integers
echo sum(10, 5);

6. ArgumentCountError

An ArgumentCountError exception is thrown when you call a PHP function without specifying a value for one of its required arguments:

function sum(int $a, int $b) : int {
    return ($a + $b);
}

// PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function sum(), 1 passed
echo sum(10);

In this example, sum() has two arguments, neither of which have default values, but only one value is passed in the function call. You can fix the error by specifying values for the missing arguments in your call.

function sum(int $a, int $b) : int {
    return ($a + $b);
}

echo sum(10, 5);

It’s easy to accidentally introduce this error when you’re adding new arguments to existing functions. Try to make any new arguments optional wherever possible, as this will preserve backwards compatibility with existing code.

7. Class Not Found and Call to Undefined Function

Class ... not found is a fatal error that’s triggered when you try to instantiate an instance of an unknown class:

// PHP Fatal error:  Uncaught Error: Class "User" not found
$myUser = new User("demo");

Similarly, call to undefined function means you’ve tried to call a function that doesn’t exist in the current namespace:

// PHP Fatal error:  Uncaught Error: Call to undefined function createNewUser()
createNewUser("demo");

These errors are normally due to one of two causes:

  • File not included: The file that defines the User class or createNewUser() function might not have been included yet. Use include() or require() to load the correct file before you try to instantiate the class or call the function.
  • Incorrect namespace: The class or function could exist in a different namespace to the current file. You should use new \My\Namespace\User() or \My\Namespace\createNewUser() syntax to specify the correct namespace.

Your code will run correctly once you’ve included the correct file and specified the class or function’s namespace.

8. Cannot Redeclare Function

A cannot redeclare function fatal error means you’ve defined a function with the same name twice:

function sum(int $a, int $b) : int {
    return ($a + $b);
}

// PHP Fatal error:  Cannot redeclare function sum()
function sum(int $a, int $b) : int {
    return ($a - $b);
}

This example demonstrates how the error can easily arise from copy-and-paste mistakes—the sum() function has been copied to create a similar subtract() function, but we forgot to change the function’s name.

Calling include() or require() on the same file is another possible cause of this error. These functions reevaluate all the code in the included file, causing the functions to be redeclared. You can avoid this by removing the second include() or require(), or using include_once()/require_once() to instruct PHP to only load the file if it hasn’t been previously included.

9. Failed to Open Stream

Failed to open stream warnings are emitted from PHP’s stream handlers when a stream can’t be created. This often happens when you’re using the HTTP stream wrapper to load content from a webpage that doesn’t exist, for example:

// PHP Warning:  file_get_contents(http://demo.localhost/example): Failed to open stream: Connection refused
$content = file_get_contents("http://demo.localhost/example");

The complete error message includes basic details about the problem — connection refused in this case.

10. Invalid Argument Supplied for Foreach

You’ll see this warning when you try to iterate over an invalid value using foreach(). Only arrays and objects can be used for iteration; any other type of value will skip the loop and show the warning.

This error is commonly seen when you try to iterate a value that’s sometimes a valid array or object, but could be undefined or null:

$items = null;

// PHP Warning:  foreach() argument must be of type array|object, null given
foreach ($items as $i) {
    echo $i -> name;
}

Fix this issue by checking that you’re passing the right variable into the foreach() loop. If the situation’s similar to the example shown above, then you can try the null coalescing operator (??) to ensure foreach() still receives a valid array when your variable is set to null:

$items = null;

foreach (($items ?? []) as $i) {
    echo $i -> name;
}

Note: Newer PHP releases display the clearer message foreach() argument must be of type array|object instead.

11. Division By Zero

PHP doesn’t support dividing numbers by zero—the operation is mathematically undefined. A DivisionByZeroError exception is thrown if your code uses zero as a denominator. This can happen if you don’t properly check your inputs to ensure they’re valid values:

$hoursPerDay = 8;
$meetingLength = 0;

// PHP Fatal error:  Uncaught DivisionByZeroError: Division by zero
echo ($hoursPerDay / $meetingLength);

$meetingLength is 0 so PHP will throw a DivisionByZeroError in this scenario

12. Dynamic Property Errors

PHP allows you to dynamically create class properties. Writing to a property that’s not defined on the class assigns the property, as if it did already exist. However, this behavior is the cause of many unexpected bugs, such as accidentally assigning to Usernamee instead of Username—PHP happily continues execution, but writes to the wrong property.

As a result, dynamic property creation was deprecated in PHP 8.2. You’ll now see deprecation warnings each time you write to a class property that hasn’t been explicitly defined:

class User {

    public function __construct(
        string $Username) {

        // PHP Deprecated:  Creation of dynamic property User::$Username is deprecated
        $this -> Username = $Username;

    }

}

$myUser = new User("demo");

// PHP Deprecated:  Creation of dynamic property User::$Active is deprecated
$myUser -> Active = true;
To resolve the problem, you must define the property on the class before you access it:
class User {

    public string $Username;

    public bool $Active;

    public function __construct(
        string $Username) {

        $this -> Username = $Username;

    }

}

$myUser = new User("demo");

$myUser -> Active = true;

You can also use the __get() and __set() magic methods to explicitly implement dynamic property behavior:

class User {

    protected array $props;

    public function __construct(
        string $Username) {

        $this -> Username = $Username;

    }

    public function __get(string $key) : mixed {
        return ($this -> props[$key] ?? null);
    }

    public function __set(string $key, mixed $value) : void {
        $this -> props[$key] = $value;
    }

}

$myUser = new User("demo");

$myUser -> Active = true;

Finally, you can choose to disable dynamic property deprecation warnings for a class by annotating it with PHP’s AllowDynamicProperties attribute. This lets you avoid modifying your code today, but you’ll still need to remove your dynamic properties ahead of the next major PHP release.

#[\AllowDynamicProperties]
class User {

    public function __construct(
        string $Username) {

        $this -> Username = $Username;

    }

}

$myUser = new User("demo");

$myUser -> Active = true;

13. Include and Require Errors

You may encounter errors when using include(), include_once(), require(), and require_once() to load other PHP files in your script. The errors are variations of the failed to open stream message detailed above, but will also display Failed opening <file> for inclusion afterwards.

// PHP Warning:  include(demo.php): Failed to open stream: No such file or directory
// PHP Warning:  include(): Failed opening 'demo.php' for inclusion
include("demo.php");

// PHP Warning:  require(demo.php): Failed to open stream: No such file or directory
// PHP Fatal error:  Uncaught Error: Failed opening required 'demo.php'
require("demo.php");

As shown by this example, include() and include_once() failures only trigger a warning—your script will continue, but the file won’t have been included. The require() and require_once() variants will trigger a fatal error if the file can’t be loaded, causing your script to terminate. To fix these errors, it’s important to check that the included file exists and is accessible to the PHP process.

14. Maximum Execution Time Exceeded Errors

PHP caps the maximum time that your scripts can run for. By default, the value is set to 30 seconds, unless you’ve manually started PHP from your terminal. This helps ensure that web requests don’t stay blocked for too long if an operation becomes stuck.

You’ll see a maximum execution time exceeded error if your script runs for longer than the configured time:

set_time_limit(5);

// Triggers after 5 seconds:
// PHP Fatal error:  Maximum execution time of 5 seconds exceeded
while (true) {
    // ...
}

This problem can be resolved in a few different ways:

  • You can optimize your code so it runs more quickly.
  • You can adjust the max_execution_time setting in your php.ini config file.
  • You can adjust the time limit from within your script by using the set_time_limit() function shown above. This allows you to easily override the default maximum execution time on a script-by-script basis.

PHP only measures your script’s direct execution time. Any time spent waiting for database operations, network calls, and system calls like sleep() is not included in the counter.

15. Undefined Constant

An undefined constant fatal error means you’ve tried to access the value of a constant that hasn’t been set:

// PHP Fatal error:  Uncaught Error: Undefined constant "DEMO"
echo DEMO;

This error is often caused by simple typos. For instance, the above example could be intended to display the text DEMO, but as there’s no quotation marks PHP has interpreted DEMO as a constant, not a string:

// Correct
echo "DEMO";

If you’re intending to refer to a constant, then you should ensure it’s defined before you access it. Use either const or define to give it a value:

const DEMO = "example";
// OR
define("DEMO", "example");

// OK
echo DEMO;

Using const sets a compile-time constant whereas define() creates runtime constants that you can also set inside conditional expressions.

How to Avoid PHP Errors

Some PHP errors are inevitable due to typos, deprecations in new PHP releases, and unexpected behavior such as a function call that takes too long to run. But it’s possible to detect and remove many types of error as you write your code, saving time spent fixing problems later on.

Here’s a few tips for reducing the number of errors you encounter:

  • Create comprehensive test suites: Unit tests let you check code outputs the expected results, both today and in the future. PHPUnit is the most popular testing framework for PHP.
  • Scan your code with static analysis tools: Static analysis tools like PHPStan scan your codebase to uncover possible errors, including coverage for areas that are missing from your test suite.
  • Conduct thorough code reviews: Reviewing code before it’s written provides an opportunity for both the author and other stakeholders to check its correctness and highlight potential errors.
  • Use AI analysis to find bugs: AI tools like Qodo Gen understand the broader context of your code. Qodo Gen analyzes your code’s actual behavior, enabling it to accurately highlight errors that may otherwise go undetected.
  • Get in the habit of using AI-powered code generation: AI agents like Qodo Gen can also create new code that meets your project’s code style and quality standards. This helps ensure that new code is kept free of errors.

These best practices won’t eliminate every error, but they’ll go a long way towards letting you deal with errors more efficiently. You can find and fix errors as you write new code, instead of waiting until it’s deployed.

Summary

PHP applications can experience many different types of errors, from benign notices through to fatal errors that immediately crash your script. Understanding the common causes of different errors allows you to spot potential problems earlier and avoid costly bug fixes after your app goes live. But this still depends on all developers recognizing potential problems.

You can find PHP errors as you work by adding Qodo Gen to your IDE. Our intelligent AI understands the context surrounding your code, enabling precision reporting of possible errors based on analysis of your entire codebase. Qodo Gen can also generate new code and test suites that align with your team’s style, letting you free up developer resources while maintaining consistent code quality standards.

Start to test, review and generate high quality code

Get Started

More from our blog

OSZAR »