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

GuntarV's avatar
Level 40

405 (Method Not Allowed) when validation fails

I have a form which submits via ajax. Now if the form validation fails, I get this error back The PATCH method is not supported for this route. Supported methods: GET, HEAD.

if validation passes, everything works as it should. I did some testing in the controller, if I return $request->all() before validation, it returns json as it should. If I add return back() I get the 405 error, the same error as if the validation fails.

This one really puzzles me. I did work as expected earlier. I probably changed something, I just cannot figure out what and why it is giving me the 405 error, instead of 422 (validation failed).

Any thoughts or suggestions?

Happy New Year everyone!!

0 likes
11 replies
Sinnbeck's avatar

Is this by any chance inertia? If not, please show your ajax code. It sounds like laravel is triggering a redirect

GuntarV's avatar
Level 40

@Sinnbeck it is vue / Laravel project.

Here is vue component method, the [this.methode] can be post or patch:

onSubmit() {
	this.form[this.methode]('/mobile/pwa-irrigations')
		.then(response => {
			console.log(response)
		})
},

I am using resource route

Route::resource('mobile/pwa-irrigations', 'PwaIrrigationController');

In controller if I return the return $request->all() it works, as soon as it hits validation and validation fails, I get the error message back in response.

public function update(Request $request, Irrigation $pwaIrrigation)
{
	//return $request->all();
	$request->validate(['attr_do_not_exist'=>'required']);
}

Here is the error message I get back in response:

{message: "The PATCH method is not supported for this route. Supported methods: GET, HEAD.",…}
exception: "Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException"
file: "E:\wamp64\www\agnote_app\vendor\laravel\framework\src\Illuminate\Routing\AbstractRouteCollection.php"
line: 117
message: "The PATCH method is not supported for this route. Supported methods: GET, HEAD."

And here is the console message:

mobile.js:4444 PATCH http://127.0.0.1:8000/mobile/pwa-irrigations/1197 405 (Method Not Allowed)

If validation passes it works as it is supposed to.

What really puzzles me is that it worked when I initially built it. I have done a lot of other additions/fixes/changes in other places in applications, but nothing in this irrigation functionality, plus this is pretty straight forward, the request does hit the controller, and everything works if validation passes, hmm...

I think somewhere in the Laravel validation on fail is logic like this, but for some reason in validation it is not seeing the request as ajax.

if ($request->ajax())) {
	return new JsonResponse($errors, 422);
}

The validation on fail is not working for both post and patch methods inside controller.

Tricky... :)

Sinnbeck's avatar

@GuntarV yeah my thought as well.

This method seems that it doesn't add the correct headers

this.form

I don't use vue so I don't know if that is a built on thing or your own implemention. Might be helpful if you show the code if it's your own

GuntarV's avatar
Level 40

@Sinnbeck It is my own implementation which I built following one of the Vue 2 tutorials here on Laracasts.

Behind the scenes it is using axios. Once the request hits the controller method, the request does come-in as ajax.

I'll keep figuring out, I do need to get it working :)

Snapey's avatar

do you ask for a json response in your form posting?

Once the request hits the controller method, the request does come-in as ajax.

because in the controller you explicitly return json

GuntarV's avatar
Level 40

@Snapey

do you ask for a json response in your form posting?

How do I do that? I did try this in the axios:

axios[requestType](url, data, params, {headers: {'Content-Type': 'application/json'}})

but that did not change anything, I am still getting back the The PATCH method is not supported for this route. Supported methods: GET, HEAD.

In the controller I checked what's coming in $request->ajax() and $request->wantsJson(), both are true

public function update(Request $request, Irrigation $pwaIrrigation)
{
	//return $request->all();
	dd($request->ajax(),$request->wantsJson());
	$request->validate(['attr_do_not_exist'=>'required']);
	dd('after validation');

If the validation fails, it is redirecting instead of returning 422 json error.

If the validation passes everything works as it should.

@snapey can you please guide me where I can find the logic on what's happening inside validate method? If I ctrl+click on it takes me to Request class,

/**
 * @method array validate(array $rules, ...$params)
 * @method array validateWithBag(string $errorBag, array $rules, ...$params)
 * @method bool hasValidSignature(bool $absolute = true)
 */
class Request extends SymfonyRequest implements Arrayable, ArrayAccess

but I don't know how to get to what's happening inside validate.

Somewhere, when the validation fails, it is redirecting instead of returning error json.

Initially when I built and tested the validation error was returned as 422 json, but at some point, it stopped doing that.

Now I am stuck in the snow :)

Snapey's avatar

Where does it redirect to (you can see this in the network tools and the response headers)

GuntarV's avatar
Level 40

@Snapey

It is redirecting to (here is a screenshot): https://prnt.sc/25fp3vo

In the applicaiton I have multiple route groups, here is a short version of two of them:

Route::prefix('mobile')->namespace('Mobile')
    ->middleware(['verified', 'auth', 'account_active'])->group(function () {
        Route::resource('pwa-irrigations', 'PwaIrrigationController');
    });
	
Route::prefix('account')->namespace('Account')
    ->middleware(['verified', 'auth', 'account_active', 'main-app-access'])->group(function () {
        Route::get('map', 'Shared\MapController@index')->name('map');
        Route::get('map/center', 'Shared\MapController@center')->name('account-center');
        Route::get('map/properties/{companyId?}', 'Shared\MapController@properties')->name('account-properties');
        Route::get('map/status-properties/{status}', 'Shared\MapController@statusProperties');
    });	

After doing some random testing, the mobile is where the validation is not working.

From the form, if I send the request to one of the account controllers and force validation to fail, validation returns 422 json as it should.

GuntarV's avatar
Level 40

Yep, it was my "programmer error". :(

Some time ago I added this redirect code in Exceptions.Handler.php inside render method:

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

	if (str_contains($request->url(),'/mobile') && auth()->check()) {
		return redirect()->route('mobile');
	}
	return parent::render($request, $exception);
}

The reason I did that is because part of my application is for mobile users (PWA). Originally, I wanted to have dedicated error pages for mobile part in the application. I could not figure out how to do that, so I decided, if there is some exception thrown in mobile part of application, just redirect user back to mobile's index page, so user stays on mobile part of the app. Later I didn't even notice that I screwed up the validation.

@sinnbeck and @snapey thank you so much for helping me to figure this out. I wish you a happy New Year!!

Please or to participate in this conversation.