loading...

Writing REST API error handling my way ?

coolgoose profile image Alexandru Bucur ・2 min read

Taking time to work more on my side project, I stumbled upon the usual issue on how to manage error handling globally on the API.

I usually would make my own structure and call it a day, but I thought it would be nice to review how other people are doing it (especially since I'm doing it in c#, a language I'm not proficient with).

So I started like everyone would with {json:api}.
Unfortunately for me there are two things that I don't like

  1. Most of the c# libraries are focused on the response not on Creating/Updating/Deleting
  2. The error handling specs and examples don't easily allow for 1:n field -> errors mapping.

To expand on the second point more let's consider the situation of a registration page.

<form>
    <label>
        email
        <input type="text" name="username">
    </label>
    <label>
        password
        <input type="text" name="password">
    </label>
    <label>
        password confirm
        <input type="text" name="password_confirm">
    </label>
</form>

Using json api's spec the response, in case the username isn't long enough and it hits a blacklist rule, would look like:

{
  "errors": [
    {
      "source": { "pointer": "/data/attributes/username", "parameter": "username" },
      "title": "Username validation error",
      "detail": "Your username needs to be at least 6 characters."
    },
    {
      "source": { "pointer": "/data/attributes/username", "parameter": "username" },
      "title": "Username validation error",
      "detail": "Your username isn't valid."
    }
  ]
}

As you can see there's no direct way of knowing which field erred out without parsing the list. I would argue that parameter usage in this case is slightly outside of the standard since it should be a string indicating which URI query parameter caused the error .

Searching further, I've stumbled upon this nice short list of how Google, Bing, Twitter, Facebook are handling the situation. Unfortunately for me, they're all returning an array of items, without any direct way of referencing the offending field.

Looking over RFC 7807 reveals a similar situation:

{
   "type": "https://example.net/validation-error",
   "title": "Your request parameters didn't validate.",
   "invalid-params": [ 
        {
            "name": "age",
            "reason": "must be a positive integer"
        },
        {
            "name": "color",
            "reason": "must be 'green', 'red' or 'blue'"
        }
   ]
}

I'm not going to go over JSend since it's a much simpler standard.

That being said, the way I envisioned having this was to just have the errors as a collection of objects, not arrays, having the following structure:

{
  "errors": {
    "username": [
      {
        "source": { "pointer": "/data/attributes/username" },
        "title": "Username validation error",
        "detail": "Your username needs to be at least 6 characters."
      },
      {
        "source": { "pointer": "/data/attributes/username" },
        "title": "Username validation error",
        "detail": "Your username isn't valid."
      }
    ],
    "password": [
      {
        "source": { "pointer": "/data/attributes/password" },
        "title": "Password validation error",
        "detail": "Your username needs to be at least 6 characters."
      }
    ]
  }
}

How are you guys handling error responses ?

Am I just lazy for not parsing the response to get to the form key or does anybody else know something that's obviously an issue with having the keys in the response ?

Posted on by:

coolgoose profile

Alexandru Bucur

@coolgoose

Programmer, Manager and a jack of all trades. Making things work since the dawn of time.

Discussion

markdown guide
 

I don't use a specific format. In one API I'm using Govalidator that returns errors like:

{
    "username": "Your username needs to be at least 6 characters.",
    "password": "Password is not a valid password"
}

The title of the error might be redundant. You already know you have a validation error for the username because the username is present in the response.

Also "errors" is probably redundant (HTTP already tells you the request failed) but we could keep it there nonetheless.

If you want to return multiple errors for a single field why not just:

{
  "username": ["Your username needs to be at least 6 characters.", "Do not use admin :D"]
}
 

I agree with you, and that's how most of the time I was doing my API replies. I was mostly curious on why people are doing it differently.

One explanation on why it's better to have an array of objects is that it's easier to map the response in strong typed languages like java or c#.

 

I guess. I've never used JSONApi so I can't comment on that either. I'm definitely, sadly, in the RESTish camp.

Technically JSON API is rest, let's say just a bit more structured.