OpenFeign/feign · error · DecodeException

is not a type supported by this decoder.

Error message

%s is not a type supported by this decoder.

What it means

JsonDecoder.decode (feign-json, built on org.json) supports only Map, JSONObject, JSONArray and String return types. When a 404/204 response is decoded to any other type, it throws DecodeException saying the type is not supported; the decoder parses JSON into org.json structures and cannot bind arbitrary POJOs.

Solutions

  1. Change the method return type to Map, JSONObject, JSONArray, or String.
  2. For 404/204 endpoints, return a supported type (Map or String yields null; JSONObject/JSONArray yield empty objects).
  3. Switch to the Jackson or Gson module for POJO decoding.
  4. Catch DecodeException around calls to not-found-prone endpoints.

Example fix

// before
UserDto getUser(); // 404 -> DecodeException
// after
org.json.JSONObject getUser(); // returns new JSONObject() on 404/204
Defensive patterns

Strategy: type-guard

Validate before calling

// before declaring a feign-json method
typeCheck(returnType);

Type guard

boolean isJsonDecoderType(java.lang.reflect.Type t) {
  if (!(t instanceof Class)) return false;
  Class<?> c = (Class<?>) t;
  return Map.class.equals(c) || JSONObject.class.isAssignableFrom(c)
      || JSONArray.class.isAssignableFrom(c) || String.class.equals(c);
}

Try / catch

try {
  result = api.get();
} catch (DecodeException e) {
  if (e.status() == 404 || e.status() == 204) {
    // unsupported return type on empty/not-found response; adjust type or handle
  } else { throw e; }
}

Prevention

When it happens

Trigger: Declaring a Feign method returning a custom POJO (e.g. MyDto) with JsonDecoder, and the server responds 404 or 204; the empty-body branch cannot map the declared type and throws.

Common situations: Using feign-json expecting POJO binding like Jackson/Gson; typed DTO returns on no-content or not-found endpoints; migrating from another decoder module.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10). Data as JSON: /api/errors/f76060a6dfe64c7c. Report an issue: GitHub.

Appendix: source

Thrown at json/src/main/java/feign/json/JsonDecoder.java:67

 *                      .decoder(new JsonDecoder())
 *                      .target(GitHub.class, "https://api.github.com");
 *
 *   JSONArray contributors = github.contributors("openfeign", "feign");
 *
 *   System.out.println(contributors.getJSONObject(0).getString("login"));
 * </pre>
 */
public class JsonDecoder implements Decoder, PredicatedDecoder, feign.codec.JsonDecoder {

  @Override
  public Object decode(Response response, Type type) throws IOException, DecodeException {
    if (response.status() == 404 || response.status() == 204)
      if (Map.class.equals(type)) return null;
      else if (JSONObject.class.isAssignableFrom((Class<?>) type)) return new JSONObject();
      else if (JSONArray.class.isAssignableFrom((Class<?>) type)) return new JSONArray();
      else if (String.class.equals(type)) return null;
      else
        throw new DecodeException(
            response.status(),
            format("%s is not a type supported by this decoder.", type),
            response.request());
    if (response.body() == null) return null;
    try (Reader reader = response.body().asReader(response.charset())) {
      Reader bodyReader = (reader.markSupported()) ? reader : new BufferedReader(reader);
      bodyReader.mark(1);
      if (bodyReader.read() == -1) {
        return null; // Empty body
      }
      bodyReader.reset();
      return decodeBody(response, type, bodyReader);
    } catch (JSONException jsonException) {
      if (jsonException.getCause() != null && jsonException.getCause() instanceof IOException) {
        throw (IOException) jsonException.getCause();
      }
      throw new DecodeException(
          response.status(), jsonException.getMessage(), response.request(), jsonException);

View on GitHub (pinned to e2a1e27560)