Table of Contents
20. A Simple Error Handler — Keeping Failures Calm
— how to let things go wrong without losing our clarity
This page closes the loop:
once we have routing, controllers, responses, queries, and API calls,
we need a way to keep failures predictable and human‑readable.
Every application fails.
A database goes down.
An API times out.
A route doesn’t exist.
A value is invalid.
Failure could happen,
so the question is:
How do we let things fail calmly,
predictably,
and intentionally?
Modern PHP gives us the tools
— exceptions, types, and predictable failure modes —
but we still need a place where all failures come together.
That place is a simple error handler.
Not a framework. Not a logging system. Not a global catch‑all that hides problems.
Just a small, intentional
home
for failure.
1. The Shape of a Calm Error Handler
A simple error handler has three jobs:
- Catch uncaught exceptions
- Log or record the failure
- Return a safe, human‑readable response
Here’s the smallest version:
set_exception_handler(function (Throwable $e) { http_response_code(500); echo 'Something went wrong.'; });
This is not production code.
It’s the shape:
- catch
- respond
- stay calm
Everything else is refinement.
2. Why This Matters
Without an error handler, PHP will:
- dump stack traces
- leak file paths
- expose internals
- confuse beginners
- overwhelm users
With a simple handler, our application becomes predictable:
- failures are contained
- responses stay consistent
- the domain stays clean
- the user sees something human
3. A Slightly Better Version
A more helpful handler logs the error
and returns a safe message:
set_exception_handler(function (Throwable $e) { error_log($e); http_response_code(500); echo json_encode(['error' => 'Internal server error']); });
This gives us:
- a record of what happened
- a predictable response
- no leaked internals
It’s enough for most small applications.
4. Giving Error Handling a Home
However, as soon as we want:
- JSON responses
- different messages for different errors
- logging
- fallback behavior
…we feel the friction.
This is the moment when error handling becomes a concept,
and we give it a home:
class ErrorHandler { public function handle(Throwable $e): void { error_log($e); http_response_code(500); echo json_encode(['error' => 'Internal server error']); } }
Our front controller now reads like a story:
set_exception_handler([$errorHandler, 'handle']);
That’s the whole point.
5. Domain Exceptions — When Failure Has Meaning
Sometimes failure is not “unexpected.”
It’s part of the domain.
Example:
class UserNotFound extends RuntimeException {}
Our controller:
try { $user = $this->users->find($id); } catch (UserNotFound $e) { return json(['error' => 'User not found'], 404); }
Our error handler catches everything else.
This separation keeps our domain expressive
and our failures intentional.
6. Why This Matters in the AI Era
When we ask AI for error handling, it may:
- hide errors
- suppress warnings
- dump stack traces
- mix logging with business logic
- generate framework‑level complexity
- use outdated patterns
Our literacy lets us steer the conversation:
“Use exceptions, not error suppression.”
“Keep the handler simple.”
“Return a safe message.”
“Log the real error.”
“Use domain exceptions for expected failures.”
We’re not memorizing error systems
— we’re shaping intention.
7. When to Ask AI for an Error Handler
The moment when failures start leaking into our controllers
Here’s what that moment looks like.
We may start with:
“Load a user by ID.”
AI gives us:
$user = $userRepository->find($id);
Then we ask:
“Handle the case where the user doesn’t exist.”
AI adds:
if (!$user) { echo 'User not found'; }
Then we ask:
“Also log the error.”
More logic.
Then we ask:
“Also return JSON.”
Even more logic.
We feel the friction.
We feel the repetition.
We feel the concept.
This is the moment to say:
“Give me a simple global error handler. Keep controllers thin and let the handler manage failures.”
AI will produce a clean handler.
This is the literacy we’re learning:
When failure repeats, ask for an error handler.
When failure has meaning, use domain exceptions.
8. The Mental Model in One Sentence
An error handler is the quiet place where failures go to rest
— calm, predictable, and safe.
Once we see this shape,
we can collaborate with AI on any error system
— from a tiny script to a full application —
without losing clarity.
Tony de Araujo —New York
