Skip to content

Using HTTP Exceptions in Slim Framework

In a REST API, exceptions need to be translated into HTTP error responses that clients can understand. The idea is simple: catch an exception and return the appropriate HTTP status code with a meaningful error message.

try {
$planet = findPlanetById($id);
} catch (InvalidArgumentException $e) {
// Bad input from the client -> 400 Bad Request
http_response_code(400);
echo json_encode(['error' => $e->getMessage()]);
} catch (NotFoundException $e) {
// Resource doesn't exist -> 404 Not Found
http_response_code(404);
echo json_encode(['error' => $e->getMessage()]);
} catch (Exception $e) {
// Unexpected server error -> 500 Internal Server Error
error_log($e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'An unexpected error occurred']);
}

This works, but it’s repetitive. You’d need similar try-catch blocks in every route. Slim Framework solves this with built-in HTTP exceptions that already know their status codes and integrate with Slim’s error handling middleware.


Slim Framework v4 introduced specialized HTTP exceptions that provide better error handling for web APIs. These built-in exceptions offer more context and control over error responses compared to generic PHP exceptions.


Slim Framework provides several specialized HTTP exceptions out of the box. These exceptions extend HttpSpecializedException and automatically set appropriate HTTP status codes.

Here are the HTTP exceptions provided by Slim Framework:

  1. HttpBadRequestException (400): For malformed requests
  2. HttpUnauthorizedException (401): For authentication failures
  3. HttpForbiddenException (403): For authorization failures
  4. HttpNotFoundException (404): For missing resources
  5. HttpMethodNotAllowedException (405): For unsupported HTTP methods
  6. HttpInternalServerErrorException (500): For server errors
  7. HttpNotImplementedException (501): For unimplemented features

Here’s how to use Slim’s built-in HTTP exceptions:

use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\HttpBadRequestException;
use Slim\Exception\HttpNotFoundException;
use Slim\Exception\HttpUnauthorizedException;
use Slim\Exception\HttpForbiddenException;
// Throw a 404 Not Found exception
throw new HttpNotFoundException($request);
// Throw a 400 Bad Request exception
throw new HttpBadRequestException($request, 'Invalid input data');
// Throw a 401 Unauthorized exception
throw new HttpUnauthorizedException($request, 'Authentication required');
// Throw a 403 Forbidden exception
throw new HttpForbiddenException($request, 'Access denied');

While Slim provides many built-in exceptions, you might need custom ones for specific business logic. You can create custom HTTP exceptions by extending HttpSpecializedException.

src/Exceptions/HttpValidationException.php
<?php
namespace App\Exceptions;
use Slim\Exception\HttpSpecializedException;
class HttpValidationException extends HttpSpecializedException
{
protected $code = 422;
protected $message = 'Validation failed.';
protected string $title = '422 Unprocessable Entity';
protected string $description = 'The request data failed validation.';
}

Throwing the custom HTTP exception:

throw new HttpValidationException($request, 'Invalid input data');

Slim’s HTTP exceptions support custom titles and descriptions that can be used by error renderers:

src/Exceptions/HttpInsufficientFundsException.php
<?php
namespace App\Exceptions;
use Slim\Exception\HttpSpecializedException;
class HttpInsufficientFundsException extends HttpSpecializedException
{
protected $code = 402;
protected $message = 'Insufficient funds.';
protected string $title = '402 Payment Required';
protected string $description = 'The account does not have sufficient funds for this transaction.';
}

Here’s how to use Slim’s HTTP exceptions in your routes:


When using Slim’s built-in error handling, HTTP exceptions will be automatically formatted into JSON responses:

Bad Request (400):

{
"message": "Bad Request.",
"exception": [
{
"type": "HttpBadRequestException",
"code": 400,
"message": "Invalid user ID: must be a positive integer",
"file": "/path/to/file.php",
"line": 123
}
]
}

Not Found (404):

{
"message": "Not found.",
"exception": [
{
"type": "HttpNotFoundException",
"code": 404,
"message": "Not found.",
"file": "/path/to/file.php",
"line": 456
}
]
}

Unauthorized (401):

{
"message": "Unauthorized.",
"exception": [
{
"type": "HttpUnauthorizedException",
"code": 401,
"message": "Authentication required to update user",
"file": "/path/to/file.php",
"line": 789
}
]
}