30

I've done it a lot of times (and seen many people do so), but I start to wonder if it is appropriate :

if @record.save
  # status 200
else
  # failure of validations => status 422
end

Now I see that 422 unprocessable entity means the request was well-formed, but not semantically correct. As I understood it, a validation error may not be a semantic error.

Note: I'm talking about uniqueness validations, so I'm not sure this qualifies as a user error, as in this question : What's an appropriate HTTP status code to return by a REST API service for a validation failure?

To sum up: should I stop using status 422 ? If so, what should I use instead ?

Community
  • 1
  • 1
m_x
  • 12,357
  • 7
  • 46
  • 60
  • __updated question:__ removed reference to status 202, because i now understand that it means 'request accepted for background processing'. My English is sometimes not good enough to understand RFC specs well... – m_x Mar 06 '13 at 17:20

4 Answers4

37

NB: tried to do a detailed answer below poke's one, but it doesn't seem to be possible, so I will answer here.

I think using 422 for validation errors is fine.

  1. The Webdav RFC doesn't say 422 means "semantic errors", it says the server was "unable to process the contained instructions" (see https://www.rfc-editor.org/rfc/rfc4918#section-11.2). "Semantic errors" are just quoted as an example use case.

  2. 500 is reserved for "an unexpected condition which prevented it from fulfilling the request" (https://www.rfc-editor.org/rfc/rfc2616#section-10.5.1).

500 is usually reserved for real errors, e.g. things that are not handled at all in your code, like crashes. Validation errors are handled, they are not "unexpected", and the client has to change the request so it can be processed (or not). In that sense, the client made the error (for instance submitting a malformed email address will throw a validation error but obviously it's not a server error, right?).

Most APIs I've seen use 400 or 422 for such cases. Maybe there's not one true answer to this, but saying that 500 is the obvious way to go seemed wrong to me.

Hope this helps.

Community
  • 1
  • 1
jbbarth
  • 712
  • 6
  • 6
  • interesting. Following Webdav RFC, it would indeed make sense to return a status 422, and "wich prevented it from fulfilling the request" clearly forbids usage of status 500. I'm just stunned that no clear consensus exists on that matter ... – m_x Aug 19 '13 at 07:10
  • 2
    In json api's generally I check for `@record.invalid?` and return a `422` first. Then check the `@record.save` and return a `200` or `500` to make sure it actually made in into the database. This is because you don't want to return a `422` if there was a problem with the server setup. – complistic Feb 06 '14 at 02:08
17

I agree with jbbarth that it's not as simple as 422 vs 500.

422 is good for validation errors, but you don't want to be catching the db errors also.

This is the pattern I use:

if @record.invalid?
  # failure of validations => status 422
elsif @record.save
  # status 200
else
  # failure when saving => status 500
end
complistic
  • 2,610
  • 1
  • 29
  • 37
11

While returning a 422 is fine, I'd say failing uniqueness validations should return a 409 Conflict.

Ho-Sheng Hsiao
  • 1,327
  • 12
  • 10
  • 1
    did not know this one, seems appropriate. If this answer gets sufficient upvotes, I'll be happy to accept it instead of the current accepted answer. – m_x Feb 26 '15 at 10:52
  • How can you differentiate between uniqueness validation failure and some other issue that caused save to fail? – don_Bigote Sep 22 '22 at 12:31
2

My understanding is that when the HTTP request was correct but you failed on the server side—for whatever reason—then you should throw a 5xx error, indicating that there was a server problem. Unless you can specify it further, a simple 500 is usually good enough.

If it is not the client’s fault, but something else (which the client can’t influence) prevented the record from being saved, then it is a server error and not a (client) error in the sense of HTTP communication.

poke
  • 369,085
  • 72
  • 557
  • 602
  • 1
    thanks. I was just reading this question: http://stackoverflow.com/questions/3066972/http-status-code-for-success-with-errors?rq=1 and the answers seem pretty much the same (and make sense). What i don't understand is why have i seen so much people use 422 in this case (especially for json), to the point i thought it was how you do it. – m_x Mar 06 '13 at 17:26
  • 2
    I think it’s mostly because people don’t know better. With all these out-of-context code snippets and everybody copying, bad solutions are being distributed easily. And sadly not everyone questions the code they see as you just did. – poke Mar 06 '13 at 17:36
  • I did not downvote, but re-reading the other answers, it occurred to me that @jbbarth's makes a lot more sense... so I changed the accepted answer, sorry – m_x Mar 13 '14 at 14:36
  • 1
    I also didn't down vote (I upvoted). but maybe someone read "for whatever reason—you should throw a 5xx error" and miss understood it? maybe changing "It's not the client’s fault" to "When it's not the client's fault" so people don't think your talking about uniqueness validation errors. (the user can try a different email address). I think all the answers here so far are correct and are saying the same thing. :) – complistic Mar 14 '14 at 08:08
  • 1
    Throwing a 500 error for a failed validation is just completely wrong. – DGM Mar 14 '14 at 23:30