Your app\Exceptions\Handler.php is the best place for this.
Maybe this helps: https://stackoverflow.com/questions/22414524/how-can-i-make-laravel-return-a-custom-error-for-a-json-rest-api#answer-38008160
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
If API request contain the header "Accept: application/json", then the standard Laravel 5.5 error handling returns a JSON object containing a "message"-field (in case of a development environment, the fields exception, file, line and trace are also present).
I am trying to alter this response to follow the JSON:API error format: http://jsonapi.org/examples/#error-objects
{
"errors": [
{
"id": "unique-trace-code-abcdefg123456798",
"code": "abcdefg123456798",
"title": "Pass this message on to the app user, if needed.",
}
]
}
Preferably, then the id would be the unique code assigned to the error by a report service like Bugsnag or Sentry.
The code should be the Exception name and the title should be the regular message.
I am wondering if this should be implemented as a condition ($request->expectsJson()) in the render() function in /app/Exceptions/Handler.php that checks if the requested format is JSON and returns a custom error Resource.
Does anyone have any experience with implementing such an error handling?
Thank you.
We ended up with a solution where we first rendered the request by the parent and then added the fields afterwards. That seemed to work for all errors.
We made the following changes to app\Exceptions\Handler.php
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
// Convert all non-http exceptions to a proper 500 http exception
// if we don't do this exceptions are shown as a default template
// instead of our own view in resources/views/errors/500.blade.php
if ($this->shouldReport($exception) && !$this->isHttpException($exception) && !config('app.debug')) {
$exception = new HttpException(500, 'Whoops!');
}
$response = parent::render($request, $exception);
// If the API request wants JSON then return custom JSON API error
if ($this->isApiCall($request) && $request->wantsJson()) {
// add fields to the content
$content = json_decode($response->getContent());
$content->links = [
'about' => App::make('url')->to('/errors/'.class_basename($exception)),
];
$content->id = app('sentry')->getLastEventID();
$content->code = class_basename($exception);
// If debug, then add debug info
if(config('app.env') !== 'production' && config('app.debug')) {
$content->debug = [
'message' => $exception->getMessage(),
'exception' => get_class($exception),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => collect($exception->getTrace())->map(function ($trace) {
return Arr::except($trace, ['args']);
})->all(),
];
}
$response->setContent(json_encode($content));
}
return $response;
}
Please or to participate in this conversation.