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

fredmarks's avatar

Exception handler 500 error

I have added an some custom exception handling for ajax request

\App\Exeptions\Handler.php


public function render($request, Exception $exception)
{

  //do something different when its an ajax call
  if ($request->ajax() && in_array($exception->getStatusCode(), array(403, 419, 404, 409))) {

      //retun ajax respone

   }

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

This is all working fine, however when my code generates a 500 error (e.g. Method does not exist) no output is generated in either debugbar or chrome developer tools.

The only place I now see the exception message is in the log file.

Any ideas how to get around this, so that I can still get my debugging exceptions for 500 errors?

0 likes
12 replies
bobbybouwmann's avatar

return parent::render($request, $exception); should handle that for you just fine. In general whenever you get a 500 error, you can see that in the response of the request in the network tab of your dev tools. It should be there!

fredmarks's avatar

@BOBBYBOUWMANN - As you have described, the exceptions are showing in my dev tools request tab as expected.

However, the problem I am having is that when I add my ajax if statement in the handler's render method as shown above, I no-longer get the exceptions being displayed in my Chome Dev tool. All I get is a white screen with no response payload

I seem to have narrowed the problem down to this

        //THIS IS CAUSING IT TO BREAK.
        if ($request->ajax()) {
            switch ($exception->getStatusCode()) {
                //it seems that this bit of code is causing the issue. No exceptions showing in dev tools
                //$exception->getStatusCode()

               //even if I suppress it with @$exception->getStatusCode(), the problem remains
            }
        }

        //THIS IS HARMLESS AND IT CONTINUES TO WORK
        if ($request->ajax()) {
            $foo = 'bar';
            switch ($foo) {
                //continues to work as expected & I still get exceptions in chrome devtool
            }
        }

bobbybouwmann's avatar

If you use a switch you need to return a given value or perform a certain action for each possible case

if ($request->ajax()) {
    switch ($exception->getStatusCode()) {
        case 404:
            return 'test';
            break;
        default
            return 'unknown';
    }
}
fredmarks's avatar

@BOBBYBOUWMANN - I do have code in the switch, I just did not put it here as it was not relevant.

if ($request->ajax()) {
      $code = $exception->getStatusCode();
}

The error is with $exception->getStatusCode(), even if all I have is the code above, when a 500 exception happens, there is nothing displayed in chrome devtool

Somehow, $exception->getStatusCode(); breaks things

bobbybouwmann's avatar

I cannot reproduce this locally. Can you share a bit more code? What is your switch doing? Did you change anything in your exception handler?

fredmarks's avatar

@BOBBYBOUWMANN -

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler {
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception) {
        parent::report($exception);
    }

    /**
     * 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) {

        if ($request->ajax()) {

            //custom ajax errors
            switch ($exception->getStatusCode()) {

            //permission denied
            case 403:
                $response = __('lang.error_no_permission_for_resource');
                break;

            //larevel session timeout
            case 419:
                $response = __('lang.error_session_timeout');
                break;

            //not found
            case 404:
                $response = __('lang.error_not_found');
                break;

            //business logic/generic errors
            case 409:
                $response = __('lang.error_request_could_not_be_completed');
                break;

            default:
                $response = __('lang.error_request_could_not_be_completed');
                break;
            }

            //return response - with error code
            return response()->json(array('message' => $response), $exception->getStatusCode());
        }

        //default laravel response
        return parent::render($request, $exception);
    }
}

Above is my full code

1 like
Snapey's avatar

What I don't understand is that when you get a 500 error, you just get a white screen.

How do you get a white screen from an ajax call? You should just see that the page stays the same, but maybe there is an error in the console?

Looks like you need to consider the client and how it handles errors.

fredmarks's avatar

@SNAPEY - I am getting the white screen (i.e. no debug output) in chrome dev tools. Also debugbar shows nothing (no exceptions).

However, If i remove that if(ajax) statement completely, then everything works. i.e. I get all the exceptions showing in dev tools and bugbar.

The only time this is breaking is with 500 exceptions. All others (like the ones in my switch statement) are working and return ajax json as expected

bobbybouwmann's avatar

@fredmarks If we look at the Laravel exception handler and the specifically to the render method we can see that it's processing the exception before returning a response!

Source: https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Exceptions/Handler.php#L161

If we eventually dive down to the core we can see the convertExceptionToResponse method. This generates a valid response for 500 errors. I think you need to give that a shut!

Also you might want to explicitly not handle any other error messages than you do now. So just remove the default case for the switch and check if you have need to return a response. Otherwise let Laravel handle it for you. The default handler also checks for ajax calls for you!

fredmarks's avatar

I managed to solve this, thanks to this thread

https://laravel.io/forum/02-19-2015-laravel-5-custom-error-view-for-500

I add this code right at the start of my render method

        if($exception instanceof \Symfony\Component\Debug\Exception\FatalErrorException) {
            return parent::render($request, $exception);
        }

In the words of the user browner12

...when your server throws an error (method does not exist, variable undefined, etc) it actually throws a FatalErrorException. as such, it is uncaught, and trickles down to the SymfonyDisplayer()

danishiqbal4's avatar

Seems like this does not work for Laravel 9. How to make this work for Laravel 9?

Please or to participate in this conversation.