This package is in pre-release. The API may change before v1.0.

Exception Handling

The toolkit provides an exception handler that renders all exceptions as JSON:API error responses, so your API never returns HTML error pages.

Setup

Register the handler in bootstrap/app.php:

use BlueBeetle\ApiToolkit\Exceptions\ConfigureExceptionHandler;

->withExceptions(new ConfigureExceptionHandler())

Exception Mapping

ExceptionStatusTitle
AuthenticationException401Unauthorized
ValidationException422Validation Error (with field pointers)
ModelNotFoundException404Not Found
NotFoundHttpException404Not Found
MethodNotAllowedHttpException404Not Found
RouteNotFoundException404Not Found
QueryException400Bad Request
LazyLoadingViolationException400Bad Request
IdempotencyExceptionvariesIdempotency Error
Domain exceptions (configurable)400Bad Request
Everything else500Internal Server Error

Validation Errors

Validation exceptions are rendered with source pointers for each field:

{
  "errors": [
    {
      "status": "422",
      "code": "validation_error",
      "title": "Validation Error",
      "detail": "The name field is required.",
      "source": {
        "pointer": "/name"
      }
    },
    {
      "status": "422",
      "code": "validation_error",
      "title": "Validation Error",
      "detail": "The email must be a valid email address.",
      "source": {
        "pointer": "/email"
      }
    }
  ]
}

Domain Exceptions

Register your application's domain exceptions so they're treated as 400 errors instead of 500s:

// config/api-toolkit.php
'exceptions' => [
    'domain' => [
        \App\Exceptions\InsufficientFundsException::class,
        \App\Exceptions\OrderAlreadyShippedException::class,
    ],
],

Debug Mode

When APP_DEBUG is true, error responses include additional debug information:

{
  "errors": [
    {
      "status": "500",
      "code": "api_error",
      "title": "Internal Server Error",
      "detail": "SQLSTATE[42S22]: Column not found...",
      "meta": {
        "debug": {
          "line": 42,
          "file": "/app/Http/Controllers/ProductController.php",
          "class": "Illuminate\\Database\\QueryException",
          "trace": [...]
        }
      }
    }
  ]
}

Suppressing Reports

Prevent certain exceptions from being logged:

// config/api-toolkit.php
'exceptions' => [
    'dont_report' => [
        \App\Exceptions\ExpectedBusinessException::class,
    ],
],

Error Response Format

All error responses follow the same JSON:API structure. Each field is included only when available:

{
  "errors": [
    {
      "status": "400",
      "code": "invalid_request_error",
      "title": "Bad Request",
      "detail": "A human-readable explanation of the error.",
      "source": {
        "pointer": "/field"
      },
      "meta": {
        "debug": { "..." }
      }
    }
  ]
}
FieldAlways presentDescription
statusYesHTTP status code as a string
codeYesMachine-readable error category
titleYesShort summary of the error
detailYesSpecific explanation for this occurrence
source.pointerValidation onlyJSON pointer to the field that caused the error
meta.debugDebug mode onlyLine, file, class, and stack trace

Error Codes

CodeUsed for
invalid_request_errorAuthentication, not found, bad request, HTTP errors
validation_errorValidation failures (422)
idempotency_errorIdempotency conflicts
api_errorUnhandled exceptions (500)