Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

aliaboussebaba's avatar

How to customize 404 message for API response

Hi, I'm using Laravel 9 as a backend Api, how can I custom the message when model not found ? My route:

Route::get('/products/{product}', [ProductController::class, 'show']);

Response 404, with json:

{
    "message": "No query results for model [App\Models\Product] 5"
}

How can I customize the message to something like:

{
    "message": "No Product found"
}

Thank you

0 likes
7 replies
bobwurtz's avatar

You can add a custom error message within the render function of App/Exceptions/Handler

use Illuminate\Database\Eloquent\ModelNotFoundException;

// ...

public function render($request, Exception $exception)
{
    if ($exception instanceof ModelNotFoundException && $request->wantsJson()) {
        return response()->json(['message' => 'Not Found!'], 404);
    }

    return parent::render($request, $exception);
}

A more complete description can be found here.

2 likes
aliaboussebaba's avatar

Thank you @bobwurtz, it's better than the default for the production. But I wonder if there is any way to customize the message based on the model, like, "Product not found", "Category not found" ? Thanks

1 like
bobwurtz's avatar

@aliaboussebaba That should be possible. If that's how you have defined your route, it doesn't look like you're using route model binding. So I'm guessing you are doing something like

public function show($product)
{
    $productData = Product::findOrFail($product);

    // more...
}

within the show function in that controller. That probably generates a default error message that you can't change. If you use Product::find($product) and then manually check if a record exists, you could return a custom JSON message if it is null.

1 like
aliaboussebaba's avatar

@bobwurtz Thank you for your reply Here is my route

Route::get('/products/{product}', [ProductController::class, 'show']);

And here is my controller

public function show(Product $product)
{
    return response()->json(product);
}

I'm coming from Symfony, autowiring is recommended, so I always inject the service in the controller instead of fetching the object in the controller every time. Your solution works fine, but I don't know what is the best practice for Laravel. Thank you

1 like
bobwurtz's avatar
bobwurtz
Best Answer
Level 2

@aliaboussebaba You're following the best practice by using show(Product $product). I just had a thought. The API docs here say that the ModelNotFound Exception has a getModel() method. You could run a switch statement in your App/Exceptions\Handler so instead of my original post it would look like this:

use Illuminate\Database\Eloquent\ModelNotFoundException;

// ...

public function render($request, Exception $exception)
{
    if ($exception instanceof ModelNotFoundException && $request->wantsJson()) {
		switch($exception->model) {
				case 'Product': return response()->json(['message' => 'Product Not Found'], 404); break;
				case 'Category': return response()->json(['message' => 'Category Not Found'], 404); break;
				// other cases...
		}
        return response()->json(['message' => 'Not Found!'], 404);
    }

    return parent::render($request, $exception);
}

I've never used this before so test it locally to see what the $exception->model actually returns and adjust the switch statement accordingly. Hope this works.

1 like

Please or to participate in this conversation.