Laravel API: Override 404 Error Message in Route Model Binding

If you use Route Model Binding in your API Controllers and the record is not found, it will automatically return the 404 status code with an error message like "No query results for model [App\Models\User] 1". How can you override it?

I'm talking about this Controller example:

VehicleController.php:

1public function show(Vehicle $vehicle) {
2 // return the API response with data
3}

In case of the model is not found in the routes/api.php based routes, it returns the JSON like this:

1{
2 "message": "No query results for model [App\\Models\\Vehicle] 1",
3 "exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
4 "file": "/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
5 "line": 391,
6 "trace": [
7 // ... full stack trace of the error
8 ]
9}

But maybe you want to have another error than "No query results for model [App\Models\Vehicle] 1"?

One reason for this may be just security: this message exposes your back-end Model name and just tells the API consumer that we probably have a Laravel project. So, any information we may hide from the consumer, increases our security, in theory.

To override this message, you need to override the whole NotFoundHttpException and return your own structure.

For that, we go to the Laravel Exception Handler file that comes by default with Laravel, and add this to the register() method:

app/Exceptions/Handler.php:

1use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2 
3class Handler extends ExceptionHandler
4{
5 public function register()
6 {
7 $this->renderable(function (NotFoundHttpException $e, $request) {
8 if ($request->is('api/v1/vehicles/*')) { // <- Add your condition here
9 return response()->json([
10 'message' => 'Vehicle record not found.'
11 ], 404);
12 }
13 });
14 }
15}

Now if you have a 404 on Vehicles, it will just return the JSON:

1{
2 "message": "Record not found."
3}

As you can see, we have an if-statement for the condition on when we want to override the message. It may be a specific endpoint for a specific model, or you may want to do it for the whole api/* with some generic message.

avatar

exactly what I was looking for thanks 🤠

avatar

great... thanks for that :)

Like our articles?

Become a Premium Member for $129/year or $29/month

Recent Premium Tutorials