Framework: FormRequest throws HttpResponseException on Validation errors

Created on 13 Feb 2016  路  27Comments  路  Source: laravel/framework

The Validation via trait throws a ValidationException, but when you go the complex route via the FormRequest class, you still get a HttpResponseException instead.

To me this looks like an oversight and the FormRequest class should throw a ValidationException as well if validation fails.

Most helpful comment

@GrahamCampbell any insight on why you closed this without any notice at all?

All 27 comments

Can you post some code?

I believe they both actually are throwing the ValidationException.

One thing to keep in mind is that a FormRequest (and using $this->validate()) both automatically handle redirection after a failed validation, which may be the reason you're seeing an HttpResponseException instead of a ValidationExeption. See below:

 /**
     * Create the response for when a request fails validation.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  array  $errors
     * @return \Illuminate\Http\Response
     */
    protected function buildFailedValidationResponse(Request $request, array $errors)
    {
        if (($request->ajax() && ! $request->pjax()) || $request->wantsJson()) {
            return new JsonResponse($errors, 422);
        }
        return redirect()->to($this->getRedirectUrl())
                        ->withInput($request->input())
                        ->withErrors($errors, $this->errorBag());
    }

So if something is wrong with that redirect, you could get another exception.

I believe the HttpResponseException may also get thrown if the authorize() method does not return true for the FormRequest, but I'm not 100% sure about that.

I am seeing this as well.

My call stack points to Illuminate\Foundation\Http\FormRequest::failedValidation as the thrower of the exception. And looking at that method:

protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException($this->response(
        $this->formatErrors($validator)
    ));
}

It clearly throws a HttpResponseException. failedValidation is called by trait ValidatesWhenResolvedTrait:

public function validate()
{
    $instance = $this->getValidatorInstance();
    if (! $this->passesAuthorization()) {
        $this->failedAuthorization();
    } elseif (! $instance->passes()) {
        $this->failedValidation($instance);
    }
}

I am using the FormRequest, am I missing something?

Yeah it looks like you're right:

Illuminate\Foundation\Http\FormRequest:

/**
     * Handle a failed validation attempt.
     *
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
     * @return mixed
     */
    protected function failedValidation(Validator $validator)
    {
        throw new HttpResponseException($this->response(
            $this->formatErrors($validator)
        ));
    }

Illuminate\Validation\ValidatesWhenResolvedTrait:

/**
     * Handle a failed validation attempt.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return mixed
     */
    protected function failedValidation(Validator $validator)
    {
        throw new ValidationException($validator);
    }

Guess I'm a little late to this one, but in the spirt of sharing and trying to help, here goes!

I'm not sure if it's intended or not, but I've worked around it for building out APIs. I basically made a class called "ApiRequest", which extends the App\HttpRequestsRequest, and added a function like such:

    /**
     * Throws an exception when validation fails.
     *
     * @see \Illuminate\Validation\ValidatesWhenResolvedTrait for more info.
     * @param Validator $validator
     * @throws ValidationException
     */
    protected function failedValidation(Validator $validator)
    {
        throw new ValidationException($validator);
    }

Agree with @mastacheata. I'm not sure what all HttpResponseException is used for, but it sounds generic. Whatever implementation is used for a validation check should receive the same exception, unless maybe a more specific one would be useful to throw.

In my case, I don't want an exception rendered back for an ajax request, so I'm checking the type of exception, and sending back a custom response object in the case of validation.

Why was this closed without any word about reasoning?
Is it fixed in a future version?
Do you think this is just a documentation problem? => In that case say so and I'll gladly file a bug against the documentation.

Returning a ValidationException for one kind of Validation and an HttpResponseException for another makes no sense at all to me, but maybe there were side effects we didn't notice that require it to return this Exception at the moment.

I long ago settled to check for an HttpResponseException when Validation fails, but I would argue it's always better to fix the root cause.

Or was it just closed as noone said anything for 2 months?
While I wasn't responding to the initial question, it seems like @HebronNor jumped in and explained the situation quite good. Also with 3 more people being able to confirm the problem I don't know what else is there to add to this issue for making it more relevant?

Having this problem today with HttpResponseException exception showing up in bugsnag, when it shouldn't be. Someone recommend adding to the ExceptionHandler, to not report on: HttpResponseException, but I don't know if it'll miss other exceptions that we'd want to see.

    protected $dontReport = [
        AuthorizationException::class,
        HttpException::class,
        ModelNotFoundException::class,
        ValidationException::class,
    ];

@GrahamCampbell any insight on why you closed this without any notice at all?

I decided to stop using the FormRequest class for now, and just put validations within the controller to make sure ValidationException was being thrown properly.

@GrahamCampbell why u closed this topic without any answer or solution? why validations/authorizations via FormRequest class should throw a different exception?

Feel free to send a PR if you want something changed.

I submitted a PR to the master branch, but I'm not sure if that is correct.
This is a backwards incompatible change due to the very nature of the problem.
However you might as well consider this a bugfix because one would probably expect a ValidationException as that is what the "simple" validation via trait throws.

Should be to 5.3, since 5.3 is not ready for release yet. We were just a little early in splitting off 5.4.

Resubmitted to 5.3 branch, I'll close that misguided PR then.

I encountered the same thing. And I think it's misleading that a validation failure causes a HttpResponseException to be thrown.
I used @trevorgehman's solution to throw the correct Exception(ValidationException), and that works well for me. So I can handle the thrown ValidationException in the render method of AppExceptions\Handler and return a JSON response(I am building an API) containing the validation messages instead of the default action of returning a stack trace(which does not make sense for a validation exception).

Hi guys,
I think the most appropriate way is to setup a custom forbidden view as the validation and authorization are different logic. So unauthorized request for a user should thrown UnAuthorizedException not ValidationException.

Hi Why This Problem Not Fixed Yet?

@ikosar It was fixed 2 years ago in 5.3 and from the way the code looks it's still the same in 5.7.
If you're still running Laravel 5.2, you've got other problems than getting a wrong Exception.

@mastacheata
Sorry,i made a mistake :(
This a reminder of the past :)

@mastacheata
My mistake is for a problem in docs !!
in "Form Request" not explain How To Handle Error Response messages.
it's redirect to 'Welcome View' directly in validations error.
My Laravel Version
"laravel/framework": "5.5.*",

Handle Validation errors?
You should probably display them to the user in human readable form.
If this is in response to the user filling out a form, a typical way would be marking the fields that contained errors with a red border.
But that is something that has to happen in your Frontend logic.
Check the Working with Error messages section

@mastacheata
No, in the docs not point to the "failedValidation" mehod In the "Form Request"!
It's defaultly redirect to another view!

In the validator::make all thing is good and work. But in "Form Request" validation errors not shown and not handling error messages

Can you show the code in the framework that defaults to the welcome view on failed validation? Form request redirect on validation error works as expected for me.

@ikosar
failedValidation throws a ValidationFailedException, which will redirect you back to where you came from and include an ErrorBag (unless you explicitly override that redirect using one of the three redirect properties)
I don't see where this would redirect you to the Welcome View (unless of course that's where you filled the form)

@mastacheata
i using APi so if it's automatically redirect There is a problem, when throw error in my request the response code is 200!
If it was said in the documentation that this was not the best?

@ikosar
Which is exactly what it is supposed to be.
A FormRequest works like this:

  1. Render a form
  2. Use fills out form and submits it
  3. POST request sent to success page
  4. success page checks if form is valid via FormRequest
  5. If FormRequest detects validation problems don't show the success page, but return to the form and include errors in session storage
  6. If FormRequest doesn't detect validation problems, it will display the success page

If you want this to behave differently, you can override the failedValidation method in your own FormRequest child class and return a different Response instead.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RomainSauvaire picture RomainSauvaire  路  3Comments

PhiloNL picture PhiloNL  路  3Comments

jackmu95 picture jackmu95  路  3Comments

ghost picture ghost  路  3Comments

iivanov2 picture iivanov2  路  3Comments