OpenFeign/feign · error · DecodeException

is not a type supported by this decoder.

Error message

{type} is not a type supported by this decoder.

What it means

StringDecoder only knows how to decode HTTP response bodies into java.lang.String (returning null for 404/204/empty bodies). When handed any other target type it throws this DecodeException, meaning the configured decoder does not support the method's return type. The thrown message names the unsupported type.

Solutions

  1. Register a decoder matching the return type, e.g. JacksonDecoder/GsonDecoder for POJOs, keeping StringDecoder for String methods via MultiDecoder
  2. Change the interface method's return type to String if you only need the raw body
  3. Use Decoder.Default (or a MultiDecoder chain ending in a default) instead of StringDecoder alone

Example fix

// before
Feign.builder().decoder(new StringDecoder()).target(Api.class, url); // method returns User
// after
Feign.builder().decoder(new MultiDecoder.Builder()
    .add(new JacksonDecoder())
    .add(new StringDecoder())
    .build()).target(Api.class, url);
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure decoder supports the method return type before the call
if (!String.class.equals(returnType)
    && decoder instanceof feign.codec.StringDecoder) {
  throw new ConfigurationException(
      "StringDecoder cannot decode " + returnType + "; register a matching decoder");
}

Type guard

static boolean stringDecoderSupports(Type type) {
  return type instanceof Class<?> c && String.class.equals(c);
}

Try / catch

try {
  return api.call();
} catch (DecodeException e) {
  if (e.getMessage().endsWith("is not a type supported by this decoder.")) {
    throw new ClientConfigurationException(
        "Return type not supported by configured decoder: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Configuring Feign with StringDecoder (directly or via ErrorDecoder/test paths that use it) while an interface method returns a non-String type such as a POJO, Response, Map, or generic type; the call decodes a 2xx non-empty body and then fails the String.class.equals(type) check.

Common situations: Using StringDecoder as the only decoder and expecting automatic JSON binding; test harnesses delegating to StringDecoder with non-String expected types; switching a method's return type from String to an object without changing decoders; confusing StringDecoder with Decoder.Default (which handles String and byte[]).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/feign/codec/StringDecoder.java:52

   */
  @Override
  public boolean canDecode(Response response, Type type) {
    return response.status() == 404
        || response.status() == 204
        || response.body() == null
        || String.class.equals(type);
  }

  @Override
  public Object decode(Response response, Type type) throws IOException {
    Response.Body body = response.body();
    if (response.status() == 404 || response.status() == 204 || body == null) {
      return null;
    }
    if (String.class.equals(type)) {
      return Util.toString(body.asReader(response.charset()));
    }
    throw new DecodeException(
        response.status(),
        format("%s is not a type supported by this decoder.", type),
        response.request());
  }
}

View on GitHub (pinned to e2a1e27560)