For the complete documentation index, see llms.txt. This page is also available as Markdown.

Exception Handling

About

In microservices or any distributed systems, remote API calls are inherently unreliable due to:

  • Network latency or timeouts

  • API version mismatches

  • Temporary service outages

  • Unauthorized or invalid requests

  • Resource not found (e.g., user doesn’t exist)

Instead of letting these issues break our application flow, proper exception handling helps us:

  • Provide informative responses to clients

  • Avoid cascading failures

  • Enable automated fallbacks

  • Log and trace failures for observability

  • Enforce clean separation of concerns between service call logic and failure behavior

How OpenFeign Handles Exceptions ?

OpenFeign does not throw HttpClientErrorException or HttpServerErrorException like RestTemplate. Instead:

  • It throws FeignException, a base class for all client errors.

  • Subtypes like FeignException.NotFound, FeignException.BadRequest represent specific HTTP statuses.

  • The exception encapsulates the raw response, status code, and response body which we can inspect or log.

1. Client-Side I/O Exceptions (Request-Time Errors)

These exceptions happen before the HTTP request even reaches the server. They usually indicate a problem in the request pipeline itself, such as:

  • Network unreachable (e.g., DNS resolution fails, host unreachable)

  • Timeout while establishing a connection

  • TLS handshake failure

  • Serialization error while preparing the request body

  • Connection reset by peer

These are different from typical HTTP response errors (like 404 or 500), because no HTTP response is returned.

How Does OpenFeign Represent These ?

When such exceptions occur:

  • OpenFeign throws FeignException or wraps lower-level exceptions (e.g., IOException, SocketTimeoutException) as RetryableException or raw RuntimeException.

In Spring Cloud OpenFeign, we can intercept these exceptions in:

  • A global @ControllerAdvice

  • A custom Feign ErrorDecoder if Feign tries to wrap it

  • A fallback method if configured

Example: Handling I/O Failures in a Safe Way

Let’s say a downstream service is unavailable, and the client fails at request time.

Feign Client Definition

Fallback Implementation

This will catch I/O-level failures and prevent the caller from crashing.

Catching Low-Level Exceptions (Manually)

If we want full control and don’t use a fallback, catch FeignException or nested IOException:

Better: Custom ErrorDecoder with Logging

Even request-time failures can be caught in a custom decoder:

Detecting Request-Time vs Response-Time Failures

To detect request-time I/O errors, we can configure Feign to use a Retryer or add a custom interceptor and logger.

2. Server Response Exceptions (Non-2xx Responses)

These occur when the request successfully reaches the server, but the server returns a non-2xx HTTP status code, such as:

  • 404 Not Found

  • 400 Bad Request

  • 401 Unauthorized

  • 500 Internal Server Error

These aren't client-side I/O errors they represent a valid HTTP response indicating server-side rejection or failure.

How OpenFeign Handles Them ?

OpenFeign by default throws a FeignException (a subclass of RuntimeException) when the server returns a non-successful HTTP status.

We can handle these exceptions by:

  • Catching FeignException in our business code

  • Defining a custom ErrorDecoder

  • Using fallbacks with @FeignClient(fallback = …)

Exception Type Mapping in Feign

HTTP Status
Feign Exception Class

4xx

FeignException.ClientError

5xx

FeignException.ServerError

Other

FeignException

Example: Basic Feign Client

Feign Client Interface

Calling the Client and Handling Server Errors

Custom ErrorDecoder to Handle Server Responses Gracefully

Instead of handling exceptions everywhere, define a central place to decode them.

Fallback Option: Safe Fallback for Errors

3. Deserialization and Response Mapping Errors

Deserialization errors occur after a successful HTTP response (i.e., a 2xx status), but when Feign tries to convert the JSON/XML body into a Java object (POJO) and fails.

These are runtime exceptions and common reasons include:

  • Mismatched or missing fields in the POJO

  • Incorrect data types (e.g., expecting int but receiving a string)

  • Invalid or unexpected response structure

  • Jackson misconfiguration

How Feign Handles Deserialization ?

Feign uses Jackson (via Spring Cloud OpenFeign) by default to deserialize the HTTP response into a Java object. If deserialization fails, it throws:

or

These typically bubble up as:

Example Scenario

Feign Client

Account POJO (Incorrect)

JSON Response

Here, deserialization will fail because Jackson looks for userName, but the JSON has username.

How to Fix / Prevent

1. Match Field Names Exactly

Use @JsonProperty if field names differ.

2. Enable Logging for Debugging

Catching Deserialization Errors Globally

Wrap our call in a try-catch and catch mapping exceptions:

Note: Jackson exceptions might get wrapped inside Feign or not be thrown directly, so sometimes using a fallback or decoding error body helps.

Using a Custom Decoder

Override Jackson decoder for finer control:

Last updated