0

In REST APIs, http error codes 4XX, 5XX are used to convey error messages on the server.

When the API itself is dependent on another backend API, is it a good practice to expose error codes or error information from the backend API call? Is there a standard for it?

Can we share the the following in the error response with 5XX?

  1. Url of the backend url
  2. parameters sent
  3. error response from backend api (when reachable)

Motivation

  1. Easy for consumer to understand error in the backend api
  2. No need to create mapping of error codes between frontend api and backend api

However, this is not desirable outside the Business Unit or the organization.

5 Answers 5

4

Remember that a REST API is an abstraction. The fact the REST API depends on other APIs is an implementation detail. Clients should be coupled to your REST API, not the other systems the REST API depends on. As soon as you pass error codes and URLs to the client, they can become coupled to your REST API's dependencies during a critical part of error handling. This would not be good practice, because error handling can be tricky. You don't want downstream changes to affect your clients, and that is precisely what happens when client error handling relies on any downstream information from the REST API.

Instead, your REST API should return a use case-specific error, and hide all details about the downstream dependency. Doing this:

  • Avoids temporal coupling between your clients and your downstream dependencies.
  • Hides sensitive information that an attacker might use to exploit your system or your downstream dependencies.

Yes, it means coming up with your own error mapping, but don't get any more detailed than is necessary for the client to recover from that error in that particular use case. If no specific error mapping is useful, return a generic 500 Server Error message or JSON response.

1

When the api itself is dependent on another backend API, it is a good practice to expose error codes or error information from the backend api call?

This is the wrong question (for "good practice") since the problem you are presenting is very dependent on the context. So I am offering a general reasoning here.

The leading questions are:

  1. Who is your audience?

  2. What is the utility of the message you are providing?

Enduser-Scenario

Say you are developing an API and your audience is the end user and his browser. What difference makes it to the user knowing "What I just did wasn't successful" or "What I just did wasn't successful, but its somebody elses fault deep down the rabbit hole". One scanrio where this may be interesting is payments. The information the payment provider has a problem could help a user to decide retrying what he did with another payment provider. But there may be many other scenarios where the additional informations is of zero utility.

Developer(Debug)-Scenario

Say your audience are developers consuming your API. The result is the same as in the enduser scenario but with the difference that they could use this information to put it in the right context: "Oh, it's not my fault querying the API wrongly nor is it a bug in the API it's further down the river. So I am fine" . The given extra information is useful in this scenario but for my taste deliverd via the wrong medium. Which leads us to the last scenario.

Production-Scenario

For production I would expect the information "The downstream API has a hiccup" appears somewhere in the logs (whatever you use). So in case anybody interested could retrieve the information (for debugging) from there. Most often you want a retry-machanism for the downstream request and use a circuit breaker which helps minimizing hiccups bubbling further upstream. And when there are endusers involved you may or may not want to provide further information.

I hope this helps deciding what you want to implement.

1
  • This surely helps.
    – Sorter
    Apr 25 at 9:56
0

If the client application is a web-based one, HTML may fit perfectly.

Just attach a text/html content to your error response from any REST-based endpoint and you're done. Works with i18n, parameters, specific scenarios, very precise error messages. All without the need for you to constantly map between "services".

Works even better, if your services link to each other instead of directly calling.

0

Yes,

Lets assume that the client library you are using to call the downstream api throws and exception with the error message. Unless you specifically want to hide or handle that exception the standard thing to do would be to bubble it up the stack and return it to the caller.

In this case thats done by returning a HTTP response indicating the error with a code (insert RESTful argument about which here) and (most of the time) a message.

However! If the error message the downstream api throws is potentially confusing, you might want to handle it by wrapping in your own exception. ie "Downstream API failed with error: {innerError}" This clearly indicates that the other api needs fixing not yours.

Maybe your language of choice has InnerException or similar, although that raises the question of how to format the HTTP error message to indicate nested exceptions.

Regarding hiding the error message for "outside" use. There are situations where you MUST do this, but I think applying that rule generally is not best practice.

It might be slightly embarrassing to expose that you are using some other company's api under the hood, but clear error messages that explicitly identify the issue are critical to resolving issues quickly.

"Cant connect to downstream api on www.wrongurl.com" 

is better than

"Error 5367912, please contact support"
-1

This is my very strong opinion, but a 500 error tells me you are not performing error handling correctly. 500 series errors are supposed to be for infrastructure issues and the default error handler for most web frameworks send that back when errors bubble out of your application.

  • 400 Bad Request means that the information presented did not make sense to the server
  • 404 There is no resource found

When it comes to errors where the request is well formed but there is some other logical error, there isn't a well defined or agreed upon standard. That said, there are a few options:

  • 403 Forbidden
  • 409 Conflict
  • 422 Unprocessable Entity

That said, 403 is probably the most appropriate. Essentially the request is well formed, but the application is refusing to process the request.

Do return a body with the error. If the endpoint typically returns JSON, XML, YAML, or some other structured format the error should be formatted in the same manner. Otherwise, you can return simple text or even an HTML page.

5
  • 1
    "[...] but a 500 error tells me you are not performing error handling correctly." I don't know how you define infrastructure, but it makes perfect sense to return a 5xx error if a downstream dependency returns a 5xx error as well that prevents your service from completing its request. The client cannot do anything to fix the issue (hence a 4xx error does not make sense). Apr 22 at 20:02
  • There are 5xx errors that are related to reverse proxies (i.e. infrastructure). If something downstream returns a 5xx error and you return something in the 5xx range would be warranted. However, the 500 error itself is when the app server itself is broken (i.e. you don't handle an exception and it bubbles out). Apr 23 at 3:20
  • 1
    should be a "like strong views, but disagree with them" button
    – Ewan
    Apr 23 at 8:05
  • In the given scenario I don't see any clue why "the application is refusing to process the request". The opposite is the case: the application is processing the request but an error occured so it can't complete the request successfully. According to the principle of least suprise - which you violate obviously here - I would wonder what "role" am I as a user missing that your API tells me what I am doing is forbidden. I do not want to downvote but appeal to rethink what you are recommending here. Apr 23 at 12:13
  • 1
    @BerinLoritsch I understand, that makes more sense to me, thank you for explaining. I think part of my confusion is that you follow this statement with a recommendation of a 4xx error as a reply, which might make sense if the downstream error is indeed caused by the client, but there's nothing in the original question that hints that it is the case. I don't see anything that could support a 403 Forbidden error in this case. Apr 23 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.