OpenFeign/feign · error · DecodeException

Cannot decode type

Error message

Cannot decode type: ${type.getTypeName()}

What it means

JacksonJrDecoder.findTransformer only knows how to decode into plain Java bean classes (or handled wrapper types); when the resolved type is neither, it throws DecodeException with the unsupported type name. jackson-jr's beanFrom requires a concrete Class, so generic or exotic types cannot be decoded by this decoder.

Solutions

  1. Change the Feign method return type to a concrete bean class that jackson-jr can map.
  2. If you need rich type support, switch to the feign-jackson (full Jackson) decoder.
  3. Register a custom decoder for the offending type via Feign.builder().decoder(new Decoder() {...}).
  4. For generic wrappers, declare them as ParameterizedTypes with Class arguments the decoder's existing handling supports.

Example fix

// before
@GET Result-interface getUsers(); // interface type -> DecodeException
// after
@GET UserList getUsers(); // concrete bean class
class UserList { public List<User> users; }
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean jacksonJrCanDecode(Type type) {
  if (type instanceof ParameterizedType) type = ((ParameterizedType) type).getRawType();
  return type instanceof Class;
}

Type guard

static boolean isBeanClass(Type type) {
  if (type instanceof ParameterizedType) type = ((ParameterizedType) type).getRawType();
  return type instanceof Class && !((Class<?>) type).isInterface();
}

Try / catch

try {
  return feignClient.call();
} catch (feign.codec.DecodeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Cannot decode type")) {
    throw new IllegalArgumentException("Return type unsupported by jackson-jr; use a concrete bean class", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Declaring a Feign method returning a non-bean type such as Object, an interface without a concrete impl, Map nested in an unsupported way, or a type that ends up neither ParameterizedType-handled nor a Class after raw-type resolution.

Common situations: Using jackson-jr module with methods typed to interfaces (e.g. List<T> declared as List but element not a Class), returning JAXBElement or custom generic wrappers, switching from the full jackson module (which handles more types) to jackson-jr.

Related errors


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

Appendix: source

Thrown at jackson-jr/src/main/java/feign/jackson/jr/JacksonJrDecoder.java:116

  }

  protected Transformer findTransformer(Response response, Type type) {
    if (type instanceof ParameterizedType) {
      Type rawType = ((ParameterizedType) type).getRawType();
      Type[] parameterType = ((ParameterizedType) type).getActualTypeArguments();
      if (rawType.equals(List.class)) {
        return (mapper, reader) -> mapper.listOfFrom((Class<?>) parameterType[0], reader);
      }
      if (rawType.equals(Map.class)) {
        return (mapper, reader) -> mapper.mapOfFrom((Class<?>) parameterType[1], reader);
      }
      type = rawType;
    }
    if (type instanceof Class) {
      Class<?> clazz = (Class<?>) type;
      return (mapper, reader) -> mapper.beanFrom(clazz, reader);
    }
    throw new DecodeException(500, "Cannot decode type: " + type.getTypeName(), response.request());
  }

  @Override
  public Object convert(Object object, Type type) throws IOException {
    String json = mapper.asString(object);
    if (type instanceof ParameterizedType) {
      ParameterizedType pt = (ParameterizedType) type;
      Type rawType = pt.getRawType();
      Type[] args = pt.getActualTypeArguments();
      if (rawType.equals(List.class)) {
        return mapper.listOfFrom((Class<?>) args[0], json);
      }
      if (rawType.equals(Map.class)) {
        return mapper.mapOfFrom((Class<?>) args[1], json);
      }
      type = rawType;
    }
    if (type instanceof Class) {

View on GitHub (pinned to e2a1e27560)