Errors, exceptions and debugging

Read error messages, handle failures with exceptions, and track down bugs systematically.

  • Beginner
  • 5 min read
  • Updated 17 Oct 2026

What you will learn

  • Read a PHP error message and find the cause
  • Configure errors for development and production
  • Throw and catch exceptions
  • Debug methodically with var_dump, error_log and Xdebug

Every developer spends a large part of their time fixing things that do not work. The difference between beginners and experienced developers is not fewer errors, it is reading them calmly and finding the cause quickly.

Reading an error message

Plain text
PHP Warning:  Undefined array key "email" in /var/www/public/contact.php on line 14

Every message tells you three things:

  1. The level: Warning, Fatal error, Parse error, Deprecated.
  2. What went wrong: here, reading a key that does not exist.
  3. Where: the file and line number.

Go to that line first. For parse errors, also check the line before, as you saw in the syntax lesson.

Error levels

LevelExample causeScript continues?
Parse errorMissing semicolon or bracketNo, nothing runs
Fatal errorCalling an undefined functionNo
WarningUndefined variable or array keyYes, but results may be wrong
DeprecatedUsing a feature that will be removedYes

Do not ignore warnings because the page "still works". A warning almost always means a value is not what you think it is, and that becomes a real bug later.

Showing errors in development, hiding them in production

While developing you want to see every error. In production, visitors must never see them: messages reveal file paths and details that help attackers.

Development (php.ini or at the top of a script while learning):

PHP
<?php

ini_set('display_errors', '1');
error_reporting(E_ALL);

Production php.ini:

INI
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
error_reporting = E_ALL

Errors are still recorded, just in a log file instead of the page. Run php --ini to find which php.ini your installation uses.

Exceptions

Many failures in modern PHP are exceptions: objects that are thrown when something goes wrong and can be caught and handled.

PHP
<?php

declare(strict_types=1);

function divide(int $a, int $b): float
{
    if ($b === 0) {
        throw new InvalidArgumentException('Cannot divide by zero.');
    }

    return $a / $b;
}

try {
    echo divide(10, 2), PHP_EOL; // 5
    echo divide(10, 0), PHP_EOL; // throws
    echo 'Never reached';
} catch (InvalidArgumentException $e) {
    echo 'Error: ', $e->getMessage(), PHP_EOL;
} finally {
    echo 'Done.', PHP_EOL;
}
Plain text
5
Error: Cannot divide by zero.
Done.
  • throw stops the function immediately.
  • try wraps code that might fail; catch handles a specific exception type.
  • finally always runs, which is useful for clean-up such as closing files.

You can catch several types, and Throwable catches everything, including engine errors like TypeError:

PHP
<?php

try {
    $result = intdiv(10, 0);
} catch (DivisionByZeroError | TypeError $e) {
    error_log($e->getMessage());
    echo 'Something went wrong with that calculation.';
}

Only catch an exception where you can do something useful: show a friendly message, retry, or use a fallback. An empty catch block hides bugs and makes them much harder to find.

A debugging method that works

When something is wrong and the message does not make the cause obvious:

  1. Reproduce it reliably. Find the exact input and steps that trigger the problem.
  2. Read the full message and go to the reported line.
  3. Check your assumptions. Print the values you are relying on:
PHP
<?php

var_dump($user);   // Shows the type and value
exit;              // Stop here so the output is easy to find
  1. Halve the search space. Put a check in the middle of the code path. Is the value already wrong there? Then the bug is earlier; otherwise it is later.
  2. Change one thing at a time and re-run.
  3. Explain the problem out loud, even to nobody. Describing it step by step often reveals the wrong assumption.

Logging instead of printing

On a live site, or inside code that produces JSON or redirects, printing breaks the output. Write to the error log instead:

PHP
<?php

error_log('Checkout total: ' . print_r($cart, true));

Using a debugger

Xdebug lets you pause code at a breakpoint, inspect every variable and step through line by line in VS Code or PhpStorm. It takes a few minutes to set up and repays that time on the first serious bug. Install it once you are comfortable with the basics.

Common beginner errors and fixes

MessageUsual causeFix
Parse error: unexpected tokenMissing ;, ) or }Check the reported line and the one before
Undefined variableTypo, or variable defined in another scopeCheck spelling; pass it into the function
Undefined array keyReading optional inputUse $array['key'] ?? default
Call to undefined functionTypo, or file not includedCheck spelling and require_once
Cannot redeclare functionFile included twiceUse require_once
Headers already sentOutput before header()Remove whitespace before <?php; omit ?>

Summary

  • Read the level, message, file and line; parse errors may start one line earlier.
  • Show errors while developing; log them, never display them, in production.
  • Use exceptions with try, catch and finally; catch only what you can handle.
  • Debug methodically: reproduce, check assumptions with var_dump, halve the search space.
  • Log with error_log() on live sites, and try Xdebug when you are ready.

You finished the course

You can now write PHP scripts, handle data with arrays and functions, process forms safely and fix errors with confidence. Take the final quiz to check your understanding, then continue with Object-Oriented PHP or PHP and MySQL.

Further reading