Change "Whoops, looks like something went wrong" page

Published 2 years ago by nurettintopal

Hi,

is there any way to change "Whoops, looks like something went wrong" page in Laravel5.

I want to use custom view page for this error.

Best Regards.

Best Answer (As Selected By nurettintopal)
nurettintopal

Hi,

thanks for your messages.

I have been using resources/views/errors/404.blade.php and 500.blade.php files. There are no any problem 4xx and 5xx exceptions.

But When the session expired, it throws TokenMismatchException. I have received "Whoops, looks like something went wrong" page in Laravel5. So, I changed the VerifyCsrfToken.php. it is OK now.

App\Http\Middleware\VerifyCsrfToken.php

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->isReading($request) || $this->tokensMatch($request)) {
            return $this->addCookieToResponse($request, $next($request));
        }
        
        return redirect("/")->with("alert", "error message to user interface");
        #throw new TokenMismatchException;
    }
    
}

If you want to display a custom error page, you need to render a view instead of redirect.

malfait.robin

In laravel you can go to App/Exceptions/Handler.php and at the bottom the render function can be edited to use a custom view.

just do something like this:

/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $e
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {
        return view('somview');
    }
dixitchopra

You can change in resources -> views -> errors -> 404.blade.php or 500.blade.php

malfait.robin

Yep, like @dixitchopra said, that's also a good option, even better actually!

ipalaus

Here is a better way:

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Exception               $e
     *
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {
        if ($e instanceof ModelNotFoundException) {
            return parent::render($request, new NotFoundHttpException);
        }

        if ( ! config('app.debug') && ! $this->isHttpException($e)) {
            return response(null, 500)->view('errors.500');
        }

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

This will still show you the full backtrace on development and, in a non-debug environment, it will show your beautiful page.

PS: In my example I also treat Illuminate\Database\Eloquent\ModelNotFoundException exceptions as 404. You don't really need to do that.

nurettintopal

Hi,

thanks for your messages.

I have been using resources/views/errors/404.blade.php and 500.blade.php files. There are no any problem 4xx and 5xx exceptions.

But When the session expired, it throws TokenMismatchException. I have received "Whoops, looks like something went wrong" page in Laravel5. So, I changed the VerifyCsrfToken.php. it is OK now.

App\Http\Middleware\VerifyCsrfToken.php

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($this->isReading($request) || $this->tokensMatch($request)) {
            return $this->addCookieToResponse($request, $next($request));
        }
        
        return redirect("/")->with("alert", "error message to user interface");
        #throw new TokenMismatchException;
    }
    
}

If you want to display a custom error page, you need to render a view instead of redirect.

JackD
JackD
1 year ago (26,065 XP)

@ipalaus this doesn't work in latest laravel version

if ($e instanceof ModelNotFoundException) {
            return parent::render($request, new NotFoundHttpException);
        }

        if ( ! config('app.debug') && ! $this->isHttpException($e)) {
            return response(null, 500)->view('errors.500');
        }

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

I've been rolling with this in /app/Exceptions/Handler.php. It just checks to see if the exception is a TokenMismatchException instance. If it is, we sort of swap it out for an HttpException that causes the /resources/views/errors/400.blade.php view to be rendered when the HttpException is then passed to the parent class for rendering. 400 is just a 'bad request' status code. You could use whatever you think is appropriate. Just create the error template to go along with it.

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    if ($e instanceof TokenMismatchException) {
        $e = new HttpException(400, $e->getMessage());
    }

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

@kkiernan A slight change is needed, as you need to checked against the full instance of the class (\Illuminate\Session\TokenMismatchException).

Meaning:

 if ($e instanceof \Illuminate\Session\TokenMismatchException) {
     // do something
 }
kkiernan

@ramonleenders Oh yeah sorry about that. I just import that class instead of writing the full name.

skunkbad

I'm not a big fan of the Whoops message...

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    if( ! config('app.debug') ) 
    {
        // MethodNotAllowedHttpException
        if( $e instanceof MethodNotAllowedHttpException )
            $e = new HttpException( 405, $e->getMessage() );

        // TokenMismatchException
        if( $e instanceof TokenMismatchException )
            $e = new HttpException( 400, $e->getMessage() );
    }

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

What about this solution? Add the following function to your Handler.php file. So far, this feels like the cleanest solution, in my opinion.


// Handler.php

protected function prepareResponse($request, Exception $e)
{
    if ($this->isHttpException($e)) {
        return $this->toIlluminateResponse($this->renderHttpException($e), $e);
    } elseif (! config('app.debug')) {
        return response()->view('errors.500', [], 500);
    } else {
        return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
    }
}
AdamEsterle

@nisaac2fly Great solution, but you may actually want to override the convertExceptionToResponse function.

Why? Because it gets called in the renderHttpException function if there is not a view for the error. I.E. No 404.blade.php file if a 404 error is thrown. It also seems to be the "catch all" function if the error is not a validation error, http error, etc.

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

        return parent::convertExceptionToResponse($e);
    }
laurence

FYI - I did a PR for this for Laravel 5.5 which has been merged.

So in 5.5 - if you have "debug" to false - it will display a custom 500 page if you have one in views/errors/500.blade.php.

https://github.com/laravel/framework/pull/18481

Please sign in or create an account to participate in this conversation.