Share

engineering

5min read

Error handling – why it’s so crucial in API design process

Error handling – why it’s so crucial in API design process

Continuous changes and improvements around us contribute to the need of making our applications dummy-proof. If our services are created to interact with the outside world we have to be prepared that there could be someone who is keen on messing with the application. If such scenario occurs, first off all think of the right approaches to tackle errors and secondly, how to do it the most RESTful way. Reading through, you’ll find out why error handling is an important aspect in the application design process.

Catch ‘em all

The worst case is when an exception is left without handling:

try {
  riskyMethod()
} catch (Exception e) {}

We always need to have a clear response in place to let the user know about the current state of the application (while developers have to have the information stored in a log). In case of an error, even a crash would look much better than no information at all. At least a critical shutdown would be immediately reported to developers and quickly fixed before a wider group of users would notice it. Vulnerable and unreliable applications may undermine developers’ reputation. For example, someone wants to comment on your recent blog post on your website. The server is experiencing problems, the user doesn’t know about the status quo and is convinced that the content has been published. It turns out they are wrong.

TIP: Remember to test all places that are vulnerable to errors.

How to achieve it?

When you realize the error handling is crucial for your service you should think of ways to improve your application’s user experience.

TIP: Catch only the exceptions you can properly handle. Don’t go for the general ones.

Applications can have multiple risky places with potential exceptions. They may derive from the database, authentication module or connection problems - the list is long. Some of these problems can be reported to the users, but most of them are incomprehensible and therefore they should be fixed before the error gets problematic. Yet too much information can reveal details about the application architecture. To avoid this, all data connected to the error should be stored in the application log and only clear messages informing about the error should be available.

error

Making the communication process even simpler you can rely on responses to errors with standardized HTTP Status Codes. Even though the list of HTTP responses is really long and sometimes its usage confuses developers, it definitely helps with framing a structure. We can distinguish two groups of errors: Client errors 4XX and Server errors 5XX. Below we have listed the most important codes:

400 - Bad request - occurs if any validation stops us.

401 - Unauthorized - means that login is required or was unsuccessful (remember it’s for authentication, not authorization).

403 - Forbidden - means that you don’t have privileges to see the requested resources (often confused with 401).

404 - Not found - the most known error. It shall be returned whenever the requested resource can’t be found.

409 - Conflict – considered as the most common code. Appears when we want to add something that already exists or the provided data is inconsistent with our app.

500 - Internal Server Error – 500 is a sign for backend developers that something went really wrong: either the server is not responding or they forgot to handle a crucial issue. On the other hand it’s a useful way of reporting problems affecting external service.

I found it really helpful to know most of the common codes and use them according to their purpose. In some simple cases, it’s enough to know them to carry a proper dialog with the frontend.

TIP: Specifying all possible answers during API design is very helpful in further test writing with expected error results.

Understanding it better

OK, so we are returning 409, 404… great, we are so RESTful, but how will the frontend know what exactly went wrong? The most important part of the backend–frontend communication process is to remember that clearly defined methods enable a smooth information stream. There are multiple options and your task is to test what works best for you:

Custom messages

HTTP/1.1 404 Not Found
Content-Type: application/json
{"status_code": 404, "error": "Not Found", "message": "Apple 1 not found"}

Recommended for: small/simple services
Pros and cons:

  • fast and simple response
  • internationalization - can be sometimes a hard nut to crack. You can implement HTTP Language parameter which is recommended (although some developers pass a language parameter in a URL which is a REST antipattern)
  • hinders code refactoring

Own error number/enum codes

Recommended for: projects with heavy documentation processes
Pros and cons:

  • very common practice
  • errors can be grouped by their destination (e.g. errors starting from 1 stand for data validation)
  • enums can be more intuitive and less abstract than numbers
  • frontend can easily add its logic – its utterly up to them how they transfer meaning behind the message. From the backend team is required a good mapping mechanism, where the actual value is a method triggered by a given error
  • implies creating more documentation

Extending HTTP exceptions with fully qualified class name

Recommended for: frameworks that return exceptions
Pros and cons:

  • gives a feeling of order
  • names indicating error meaning
  • some frameworks (e.g. Spring) return the exception name by default (so it’s ready to use)
  • frontend is parsing Strings to know which exception was thrown by backend
  • requires good frontend-backend communication
  • reveals some details of backend architecture
  • hinders code refactoring

The broad range of possibilities doesn’t necessarily mean we can freely choose from the available methods. Often the used framework forces us to apply a specific mechanism; however they can be combined with other solutions.

In the loop

Without doubt, error handling is an important part of the application design process. For that reason we should analyze different aspects of our project and choose wisely between various approaches. The more precisely we do it, the easier it will be to achieve a satisfying communication level between frontend and backend, subsequently leading to a greater application user experience.

And how about you? What’s your experience with error handling? Looking forward to your comments.

Share

Katarzyna

Senior Software Engineer

Did you enjoy the read?

If you have any questions, don’t hesitate to ask!

Did you enjoy the read?

If you have any questions, don’t hesitate to ask!