How to send Laravel error responses as JSON
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# How to Send Laravel Error Responses as JSON: Bridging the Gap from HTML Errors
Migrating between major versions of a framework often involves more than just updating syntax; it requires understanding fundamental shifts in how exceptions and HTTP responses are handled. Youâve encountered a very common challenge: moving from environments where errors were naturally returned in structured JSON formats (like older Laravel versions) to newer setups where exceptions sometimes default to rendering raw HTML, which is unacceptable for building robust APIs.
As a senior developer, I can tell you that treating errors as simple text displayed on the screen defeats the purpose of an API. Consumers need predictable, machine-readable dataâJSONâto handle failures gracefully. This post will walk you through the correct, Laravel-idiomatic way to ensure all your application errors are consistently delivered as JSON responses, even when dealing with exceptions like `NotFoundHttpException`.
## Why Raw HTML Errors Are a Problem for APIs
When an exception is thrown in a standard Laravel request lifecycle and not properly caught or formatted by the framework's exception handler, it often falls back to rendering a view (like a Blade template). This results in the user seeing raw error messages embedded directly into the HTML response, as you observed: `NotFoundHttpException in Application.php line 756: Persona no existe`.
For an API endpoint consumed by mobile apps, JavaScript clients, or other services, this output is useless. They cannot reliably parse the error details to implement proper user feedback or retry logic. The goal of modern application design, especially when building APIs, is to separate the *logic* (the error) from the *presentation* (the HTML). We need a mechanism to intercept the exception and convert its data into a standardized JSON payload.
## The Laravel Solution: Customizing the Exception Handler
The most robust and scalable way to handle this across your entire application is by customizing Laravel's built-in exception handling mechanism, specifically within `app/Exceptions/Handler.php`. This file acts as the central gatekeeper for all exceptions thrown by your application.
You need to override the `render()` method in your custom handler to check if the request expects a JSON response (typically when the `Accept` header is set to `application/json`) and format the exception details accordingly.
Here is a conceptual example of how you would modify your `render` method:
```php
// app/Exceptions/Handler.php
use Illuminate\Http\Request;
use Throwable;
use Illuminate\Http\JsonResponse; // Import JsonResponse
class Handler extends ExceptionHandler
{
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $exception
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Throwable $exception)
{
// Check if the request expects a JSON response
if ($request->wantsJson() || $request->is('api/*')) {
// Format the error into a standardized JSON structure
return response()->json([
'error' => [
'type' => get_class($exception),
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]
], $exception->getStatusCode());
}
// For all other cases (e.g., standard web views), use the default behavior
return parent::render($request, $exception);
}
}
```
This approach ensures that any time an exception occurs on an API endpoint, it is automatically transformed into a clean JSON response containing the necessary context (`type`, `message`, file location). This aligns perfectly with building clean APIs, promoting consistency across your application, much like the principles advocated by the [Laravel team](https://laravelcompany.com).
## Alternative: Handling Errors in Controllers
For simpler scenarios or specific API routes, you can also handle errors directly within your controller methods using `try-catch` blocks. This gives you granular control over the response for that specific endpoint.
```php
// Example Controller Method
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
public function show($id)
{
try {
$person = Person::findOrFail($id);
return response()->json($person);
} catch (NotFoundHttpException $e) {
// Manually return the desired JSON format
return response()->json([
'error' => [
'type' => 'NotFoundHttpException',
'message' => 'Person does not exist',
'file' => '...', // You can add more context here if needed
'line' => 768
]
], 404);
}
}
```
While the exception handler is best for global consistency, using `try-catch` in controllers provides immediate, explicit control over API responses.
## Conclusion
Moving from older Laravel patterns to modern expectations requires shifting focus from presentation (HTML) to data transfer (JSON). By mastering the customization of the Exception Handler, you establish a centralized, predictable error management system for your entire application. Whether you opt for global exception handling or specific controller catching, ensuring that all errors are serialized into structured JSON is the key to building reliable and professional APIs. Keep focusing on solid architectural patterns; they make development much smoother, whether you are working with Laravel 5 or any subsequent version.