Support the ongoing development of Laravel.io →
Configuration Views
Last updated 2 years ago.
0

Had same problem, not quite sure why this happens. Maybe we need to specify something special for 500 error in inscription/app/Exceptions/Handler.php?

I found Mat Stauffer's post saying it works with 404.blade.php, but no word on 500.blade.php

On production with DEBUG=false, I still get that Laravel default page laravel5-500-error-on-production.png

Last updated 6 years ago.
0

This test works for me in Laravel 5. Navigating to the route loads my views/errors/500.blade.php view. Placing the error view in any other directory does not work for me by default.

Route::get('500', function()
{
    abort(500);
});
Last updated 9 years ago.
0

so the problem is that Laravel will only do this automatic rendering of error pages for exceptions that are instances of HttpException. unfortunately 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() which either gives you the trace (debug true) or ugly one liner 'Whoops, looks like something went wrong' (debug false).

the reason abort(500) works is that it specifically throws an HttpException with a status code of 500.

if anyone has come up with a good solution to this, i would love to hear it. for now I'm specifically catching FatalErrorExceptions in my handler.

0

Yes an HttpException must be thrown to show the view.

0

browner12 said:

..... for now I'm specifically catching FatalErrorExceptions in my handler.

Are you using instanceof to do that ? I'm trying to build a custom page for FatalErrorException. Having the default Whoops page for production is unacceptable.

Last updated 9 years ago.
0

There is not only FatalErrorException, but also RuntimeException and other, so here is my render method that catch any server errors (file app/Exceptions/Handler.php) :

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

    // 404 page when a model is not found
    if ($e instanceof ModelNotFoundException) {
        return response()->view('errors.404', [], 404);
    }

    if ($this->isHttpException($e)) {
        return $this->renderHttpException($e);
    } else {
        // Custom error 500 view on production
        if (app()->environment() == 'production') {
            return response()->view('errors.500', [], 500);
        }
        return parent::render($request, $e);
    }

}
Last updated 9 years ago.
0

For Laravel 5.1 :

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

    // 404 page when a model is not found
    if ($e instanceof ModelNotFoundException) {
        return response()->view('errors.404', [], 404);
    }

    // Custom error 500 view on production
    if (app()->environment() == 'production') {
        return response()->view('errors.500', [], 500);
    }

    return parent::render($request, $e);

}
0

If anyone is wondering how to catch it, use:

if($e instanceof \Symfony\Component\Debug\Exception\FatalErrorException) {
	$statusCode = 500;
}
Last updated 9 years ago.
0

I have tried the above code but i didn't work when the Exception is of type \PDOException and the DB server is unavailable or the credential details are wrong:

if ($e instanceof \PDOException) {
    // This is not working when database is unavailable or the login details are wrong...
    return response()->view('errors.404', ['message', $e->getMessage()], 404);
}
Last updated 9 years ago.
0

For me this worked in Laravel 5.2

app/Exceptions/Handler.php

public function render($request, Exception $e)
{
    // ... other checks like for TokenMismatchException

    // custom error message
    if ($e instanceof \ErrorException) {
        return response()->view('errors.500', [], 500);
    } else {
        return parent::render($request, $e);
    }

}
0

Not to beat a dead horse, For some reason none of the above solutions worked for me.

Here is my solution.

app/Exceptions/Handler.php

Add this to your render method.

https://gist.github.com/adampatterson/e86ac67d321932ecd787f060ae6bdb81

Last updated 8 years ago.

athospy liked this reply

1

When adding custom 500 error, if user makes mistake instead of showing validation it throws them to 500 error view.

Anybody had same problem?

public function render($request, Exception $e)
    {
        if (config('app.debug') || parent::isHttpException($e)) {
            return parent::render($request, $e);
        }

        return response()->view("errors.500", [], 500);
    }
Last updated 8 years ago.
0

I have same problem as Erse.

public function render($request, Exception $e)
{
    $exception = \Symfony\Component\Debug\Exception\FlattenException::create($e);
    $statusCode = $exception->getStatusCode($exception);

    if (env('APP_DEBUG') == FALSE && $statusCode == 500 && $e instanceof ValidationException != TRUE) {
        return response()->view('errors.500', [], 500);
    } else {
        return parent::render($request, $e);
    }
}

My solution is test instance of $e, if it is ValidationException.

Is there any other type of exception, which shouldn't be catch by error page?

Last updated 8 years ago.
0

@erse and @fabiancz, if you look at the parent render method you can see what exceptions it catches (link). There are a couple more like ModelNotFoundException and AuthorizationException.

Since the handler extends the parent handler, I just override the method that builds the symfony response for non-http exceptions. That way the existing handler still handles any HTTP exceptions, validation exceptions etc. If in debug mode I still use the original method since it has stacktrace etc.

namespace App\Exceptions;

class Handler extends ExceptionHandler
{
    // existing code up here...
    
    protected function convertExceptionToResponse(Exception $e)
    {
        if (config('app.debug')) {
            return parent::convertExceptionToResponse($e);
        }

        return response()->view('errors.500', [], 500);
    }
}
0

This solution (from @matthewjames) worked really well for me. The only problem I had was that my 500 page view was repeated multiple times on screen, if there were multiple errors on a page.

I resolved this by adding this an ob_clean() to the code, as follows:

protected function convertExceptionToResponse(Exception $e)
{
	if (config('app.debug')) {
		return parent::convertExceptionToResponse($e);
	}
	ob_clean();
	return response()->view('errors.500', [], 500);
}

This feels like a clunky fix, though -- there may be a much better approach.

0

Hi guys ,

My solution ->

public function render($request, Exception $exception)
    {
        if ($exception instanceof \ErrorException) {
            $response = response()->view('errors.500', [], 500);
            return  $this->toIlluminateResponse($response,$exception);
        }

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

I've put together your solutions, with additional condition: In my app user not logged in is not allowed to see any other page than login/register.


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

    // Render full exception details in debug mode
    if(config('app.debug')) {
        return parent::render($request, $e);
    }

    // Redirect if token mismatch error
    // Usually because user stayed on the same page too long and his session expired
    if ($e instanceof TokenMismatchException) {

        // if it's ajax request send back "unauthorized" status response
        // then in js/jQuery you catch and redirect all those 401 responses:
        // $.ajaxSetup({ statusCode: { 401: function() { window.location.href = '/your_login_page'; } } });
        if ($request->ajax()){
            return response('Token Mismatch Exception', 401);
        }

        // redirect to login page
        return redirect()->route('auth.login.get');
    }

    // Model not found
    if ($e instanceof ModelNotFoundException) {

        // it could be useful to get not founded model name and pass it to 404 error page:
        // $model = $e->getModel();
        // $baseModel = new $model;
        // $resourceNotFounded = class_basename($baseModel);
        // return response()->view('app.errors.404', compact('resourceNotFounded'), 404);


        // or simply redirect to not found page
        return response()->view('app.errors.404', [], 404);
    }

    // Http exceptions
    if ($this->isHttpException($e))
    {
        // redirect to login if not authenticated
        // I don't want to let unauthenticated users to see error pages
        if( ! \Auth::check() ){
            return redirect()->route('auth.login.get');
        }


        // try to find right error page for this exception
        // I have prepared 4 most common errors: 403,404, 500 and 503
        $exception = FlattenException::create($e);
        $statusCode = $exception->getStatusCode($exception);

        if (in_array($statusCode, array(403, 404, 500, 503))){
            return response()->view('app.errors.' . $statusCode, [], $statusCode);
        }
    }

    // uncomment line below if you want 500 error page for all other errors
    // I prefer to use default behavior for them
    //return response()->view('app.errors.500', [], 500);

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

Used classes have to be imported with "use", or written with full path.

Last updated 7 years ago.
0

gart77 that is awesome, thank you!

0

I pen a package to get error pages. You can check here https://github.com/enniosousa/server-error-pages

0

Sign in to participate in this thread!

Eventy

Your banner here too?

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.