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

elo's avatar
Level 3

Return json response for only API 404 error

I have exposed the API of a laravel 5.7 application. My goal is to return json response for all API calls that results in a 404 error.

This is how I have gone about achieving my goal

I modified the app\Exceptions\Handler.php file like this

// Add this at the top after namespace
use Illuminate\Database\Eloquent\ModelNotFoundException;

// Edited the render method like this
public function render($request, Exception $exception)
{
    if ($exception instanceof ModelNotFoundException && $request->wantsJson()) {
        return response()->json(['error' => 'Book Not found'], 404);
    }

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

And add a fallback route to routes\api.php file like this

Route::fallback(function(){
    return response()->json(['message' => 'Page Not Found'], 404);
});

With this a call to a route that doesn't exist returns this {"message":"Page Not Found"} correctly but a call to localhost:8000/api/books/1 returns the default laravel 404 page which is not the behavior I am looking for.

If i remove && $request->wantsJson() from the render method, both calls made to localhost:8000/books/1 & localhost:8000/api/books/1 return {"error":"Book Not found"}. But this also is not what i want.

Target Behavior:

get localhost:8000/books/1 return default laravle 404 not found page

get localhost:8000/api/books/1 return json response

How can I achieve this?

0 likes
10 replies
YeZawHein's avatar

@elo Try this

//handler.php
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

 public function render($request, Exception $exception)
    {
        if ($exception instanceof NotFoundHttpException) {
            return Route::respondWithRoute('fallback');
        }

        if ($exception instanceof ModelNotFoundException) {
            return Route::respondWithRoute('fallback');
        }

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

//api.php
Route::fallback(function () {
    return response()->json(['error' => 'Not Found!'], 404);
});

elo's avatar
Level 3

@YEZAWHEIN - It throws an error

Symfony\Component\Debug\Exception\FatalThrowableError thrown with message "Class 'App\Exceptions\Route' not found"
elo's avatar
Level 3

@CALEX - Actually tried doing that but got the same error. Been at this for 2days now

YeZawHein's avatar

@elo This error means Handler.php not found fallback function.Try debug in api.php

Route::fallback(function () {
   dd(here);
});
YeZawHein's avatar

@elo

get localhost:8000/books/1 return default laravle 404 not found page

get localhost:8000/api/books/1 return json response

Now I realize your problem. That error should be in web.php.You don't have fallback function for web.php.You can create custom 404 view.

//handler.php
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

 public function render($request, Exception $exception)
    {
        if ($exception instanceof NotFoundHttpException) {
            return Route::respondWithRoute('fallback');
        }

        if ($exception instanceof ModelNotFoundException) {
            return Route::respondWithRoute('fallback');
        }

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

//api.php
Route::fallback(function () {
    return response()->json(['error' => 'Not Found!'], 404);
});

//web.php
Route::fallback(function () {
    return view('errors.404'); //custom view
});

If you want to laravel default 404 page, you can clear logic inhandler.php

//api.php
Route::fallback(function () {
    return response()->json(['error' => 'Not Found!'], 404);
});

//web.php
Route::fallback(function () {
    return abort(404); //default 404
});

elo's avatar
Level 3

@YEZAWHEIN - @yezawhein I just tried out this method but got the same result. I going to keep trying as I believe that it's achievable.

developre's avatar

You can receive the exception in render function in Handler.php and you may check the request is from API or typical.

            if($request->is('api/*')){
        // your stuff
    }
vijayrana's avatar

I know this is an old thread but may help future readers. I solved it with the following approach. Add at the end of your api.php (below all of the other routes) something like


Route::any('{path}', function() {
    return response()->json([
        'message' => 'Route not found'
    ], 404);
})->where('path', '.*');

Ali-Habib's avatar

@vijayrana Hi I did that but it's still not woking for me. I did not use anything in Handler, just put your route code in api.php

Please guide me in detail.

Please or to participate in this conversation.