you might want to check this part of the Laravel Docs: https://laravel.com/docs/5.8/errors#custom-http-error-pages
You can change/add error handling pages :)
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
How can I get the routes to send the user to the standard 404 page if they access a path that is not a defined route. I am getting "{METHOD} not supported for this route" while in debug mode and without debug mode it just says "Whoops, looks like something went wrong."
For instance accessing a POST only route via the browser GET I want to send to a 404 page vs this error message.
Thanks
you might want to check this part of the Laravel Docs: https://laravel.com/docs/5.8/errors#custom-http-error-pages
You can change/add error handling pages :)
Thanks for the link. But why does it work this way as far as the code goes since I specially state a path and method if it doesn't exists in my route definitions it shouldn't treat going to a path with the wrong method different then going to a route that doesn't exists at all with any methods. At least that's my opinion, what is the reasoning behind doing different error handling for this situation by default?
Can you show your routes file?
It sounds like the order of your routes might cause this. If you have for example first a route ‘products/{product}’ followed by a route ‘products/sale’ the router will try to resolve ‘sale’ as a product. If you first declare the specific sale route, this will not happen.
@MTHOMAS - I removed all routes except this one and it still gives the same {METHOD} not supported for this route error instead of a 404.
Route::post('/admin/user/list/ajax', 'UsersController@ajaxList');
If I access this via /browser/GET
You won't be able to access a POST Route as a GET. If you want to be able to visit the page in a browser or make a GET request, you need to register a get route:
Route::get('/admin/user/list/ajax', 'UsersController@ajaxList');
That is also the reason you will get the Method not supported error, you don't have a matching rout in your routes file that supports that method.
If you want to be sure that you will get a 404 for the get route, register a route (can be a closure) that will handle the get request and present the visitor with a 404:
Route::get('/admin/user/list/ajax', function() {
return abort(404);
});
@MTHOMAS - I was just running tests to see what would happen if someone tried to access the url they see in javascript. I am not wanting to access it via GET I just wanted to know what happens if someone else tries to access it. I really don't want to have to manually add invalid routes just to show 404 errors I just wanted the system to treat all routes "not defined by me" the same way. But it seems it treats routes differently if you have at least one route that's similar vs one that doesn't match anything.
ah I see what you don't like. A solution can be that you change the default error handling (and you should realize that the error pages shown in your local development environment are differently styled that those on production). That way you can change the appearance of your error pages on production.
Check the fallback route
https://laravel.com/docs/5.8/routing#fallback-routes
Route::fallback(function () {
//Send to 404 or whatever here.
});
@TRAY2 - Thank you that's perfect!
@TRAY2 - Actually I just ran into the issue again but with POST. The fallback does not work with methods other then GET. When I post to an invalid route (I forgot to update a url and found this out by accident) I ended up getting "The POST method is not supported for this route. Supported methods: GET, HEAD, PATCH." But since it was an invalid route altogether it should have been caught with the standard 404 but it wasn't.
If you really want to change the error, you could change the error rendering method for the exception being thrown:
The issue was that the instanceof check in your Handler class was not working correctly. Specifically, the instanceof operator was failing to recognize the MethodNotAllowedHttpException as an instance of Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException. This caused your custom logging logic to be skipped, even though the exception was being logged by Laravel's default exception handler.
Root Cause The root cause was likely one of the following:
Namespace Issue: The MethodNotAllowedHttpException class was not being referenced with its fully qualified namespace (Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException). This caused the instanceof check to fail.
Class Aliasing or Autoloading Issue: There might have been an issue with how the MethodNotAllowedHttpException class was being autoloaded or aliased in your application.
How It Was Fixed The issue was resolved by:
Fully Qualifying the Exception Class: Ensuring that the MethodNotAllowedHttpException class was referenced with its fully qualified namespace (Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException) in the instanceof check.
Adding Debugging Logs: Adding debugging logs to confirm the exact class of the exception and ensure that the instanceof check was working correctly.
Why the Custom Template Worked The custom template (errors.method-not-allowed) was being rendered because the renderable callback in your Handler class was correctly registered and executed. The renderable callback does not rely on the instanceof check in the report method, so it was unaffected by the issue.
Final Explanation Here’s a summary of what happened:
Exception Thrown: A MethodNotAllowedHttpException was thrown because an unsupported HTTP method (e.g., GET) was used for a route that only supports POST.
Exception Logged by Laravel: Laravel's default exception handler logged the exception, resulting in the log:
Copy [2025-02-25 20:29:20] local.INFO: Exception class: {"exception":"Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException"} Custom Logging Skipped: The instanceof check in your Handler class failed, so your custom logging logic (Log::error('MethodNotAllowedHttpException occurred: ' . $e->getMessage());) was skipped.
Custom Template Rendered: The renderable callback was executed, rendering the custom template (errors.method-not-allowed).
After fixing the instanceof check, your custom logging logic started working, and you saw the additional logs:
Copy
[2025-02-25 20:29:20] local.INFO: MethodNotAllowedHttpException detected in report method.
[2025-02-25 20:29:20] local.ERROR: MethodNotAllowedHttpException occurred: The GET method is not supported for this route. Supported methods: POST.
Key Takeaways
Always Use Fully Qualified Class Names: When using instanceof, always reference the class with its fully qualified namespace to avoid issues.
Debugging Logs Are Essential: Adding debugging logs can help you identify and resolve issues quickly.
Separate Logging and Rendering Logic: The report method (for logging) and the renderable callback (for rendering) are independent. Issues in one do not necessarily affect the other.
Final Working Code Here’s the final version of your Handler class with all the fixes:
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Throwable;
use Log;
class Handler extends ExceptionHandler
{
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
// Log MethodNotAllowedHttpException
$this->reportable(function (MethodNotAllowedHttpException $e) {
Log::info('MethodNotAllowedHttpException reportable callback executed.'); // Debugging
Log::error('MethodNotAllowedHttpException occurred: ' . $e->getMessage());
});
// Render MethodNotAllowedHttpException
$this->renderable(function (MethodNotAllowedHttpException $e, $request) {
return response()->view('errors.method-not-allowed', [], 405);
});
}
/**
* Report or log an exception.
*
* @param \Throwable $e
* @return void
*/
public function report(Throwable $e)
{
// Debugging: Log the exact exception class
Log::info('Exception class:', ['exception' => get_class($e)]);
// Debugging: Log the fully qualified exception class
Log::info('Exception fully qualified class:', ['exception' => get_class($e)]);
// Check if the exception is MethodNotAllowedHttpException
if ($e instanceof MethodNotAllowedHttpException) {
Log::info('MethodNotAllowedHttpException detected in report method.'); // Debugging
Log::error('MethodNotAllowedHttpException occurred: ' . $e->getMessage());
} else {
Log::info('Exception is not a MethodNotAllowedHttpException.'); // Debugging
}
// Call the parent report method
parent::report($e);
}
}
Expected Behavior With the fixes in place, here’s what happens when a MethodNotAllowedHttpException occurs:
The exception is logged by Laravel's default exception handler.
The instanceof check in your Handler class detects the exception and executes your custom logging logic.
The reportable callback logs the exception.
The renderable callback renders the custom template (errors.method-not-allowed).
Use the code below for /app/Exceptions/Handler.php
Create template in /resources/views/errors/method-not-allowed.blade.php
Laravel Framework 8.83.28
Please or to participate in this conversation.