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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
   "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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "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 ?