Error Handling

Slim ships with a built-in ErrorMiddleware that catches uncaught exceptions and PHP errors, then turns them into an HTTP response instead of a blank page or a raw stack trace dumped straight to the browser. How much detail that response shows — and whether it shows up as HTML or JSON — is entirely up to how you configure it.

Adding the Error Middleware

You enable it with a single call, right after you create the app:

<?php
require __DIR__ . '/../vendor/autoload.php';

$app = \Slim\Factory\AppFactory::create();

$displayErrorDetails = true;  // set to false in production
$logErrors = true;
$logErrorDetails = true;

$app->addErrorMiddleware($displayErrorDetails, $logErrors, $logErrorDetails);

$app->run();

The three arguments map directly to the three things you care about: show the reader what went wrong, write it to a log file, and include the full detail (stack trace, file, line) in that log entry.

Development vs Production

DevelopmentProduction
$displayErrorDetailstrue — see the full error on screenfalse — visitors see a generic message
$logErrorstrue (helpful, not required)true — you still need the record
Who sees the traceYou, in the browser, instantlyOnly you, in the log file

A common pattern is to drive the flag from an environment variable so the same code works in both places:

<?php
$displayErrorDetails = ($_ENV['APP_ENV'] ?? 'production') === 'development';

$app->addErrorMiddleware($displayErrorDetails, true, true);

Custom Error Handlers

addErrorMiddleware() returns the middleware object itself, which lets you register a custom handler for a specific exception type — for example, a nicer page (or response) for a 404 instead of Slim's default HTML error output:

<?php
use Slim\Exception\HttpNotFoundException;

$errorMiddleware = $app->addErrorMiddleware(true, true, true);

$customNotFoundHandler = function ($request, $exception, $displayErrorDetails, $logErrors, $logErrorDetails) use ($app) {
    $response = $app->getResponseFactory()->createResponse();
    $response->getBody()->write('Sorry, that page could not be found.');
    return $response->withStatus(404);
};

$errorMiddleware->setErrorHandler(HttpNotFoundException::class, $customNotFoundHandler);

You can register a different handler for each exception class, or one setDefaultErrorHandler() that catches everything else.

Returning JSON Errors for an API

If your Slim app is a JSON API (see Building JSON APIs), the default HTML error page is the wrong shape entirely — callers expect JSON back, even when something goes wrong. Build the error body yourself and set the content type explicitly:

<?php
use Slim\Exception\HttpNotFoundException;
use Psr\Http\Message\ServerRequestInterface;

$errorMiddleware = $app->addErrorMiddleware(false, true, true);

$jsonNotFoundHandler = function (
    ServerRequestInterface $request,
    Throwable $exception,
    bool $displayErrorDetails,
    bool $logErrors,
    bool $logErrorDetails
) use ($app) {
    $payload = ['error' => 'Not Found'];

    $response = $app->getResponseFactory()->createResponse();
    $response->getBody()->write(json_encode($payload));

    return $response
        ->withHeader('Content-Type', 'application/json')
        ->withStatus(404);
};

$errorMiddleware->setErrorHandler(HttpNotFoundException::class, $jsonNotFoundHandler);

A request to a route that doesn't exist now gets back {"error": "Not Found"} with a 404 status, instead of an HTML page a JSON client can't do anything with.

Warning: Never leave $displayErrorDetails = true in a production deployment. It leaks full stack traces, file paths, and sometimes database credentials or query text straight to whoever is looking at the response — including attackers. Always flip it to false and rely on your logs instead.
Next steps: Now that errors are handled cleanly, head to Working with a Database to connect Slim to real data using PDO.