OpenFeign/feign · error · UnsupportedOperationException

JAXB only supports decoding raw types. Found

Error message

JAXB only supports decoding raw types. Found ${type}

What it means

The javax-based jaxb module's JAXBDecoder.decode unwraps ParameterizedTypes and then requires the resulting type to be a plain Class; otherwise it throws UnsupportedOperationException, because JAXB can only decode into raw JAXB-annotated classes.

Solutions

  1. Return a raw JAXB-annotated class instead of a generic type.
  2. Wrap collections in an @XmlRootElement wrapper DTO.
  3. Switch to a JSON decoder module for generic return types.

Example fix

// before
List<Item> list();
// after
@XmlRootElement
class ItemList { @XmlElement(name="item") List<Item> items; }
ItemList list();
Defensive patterns

Strategy: type-guard

Validate before calling

// before declaring/calling
typeCheck(methodReturnType);

Type guard

boolean isJaxbDecodable(java.lang.reflect.Type t) {
  while (t instanceof ParameterizedType) {
    t = ((ParameterizedType) t).getRawType();
  }
  return t instanceof Class;
}

Try / catch

try {
  dto = api.call();
} catch (UnsupportedOperationException e) {
  // change the return type to a raw JAXB class or switch decoder
}

Prevention

When it happens

Trigger: Declaring a Feign method whose return type reduces to a non-Class (e.g. a generic wrapper that survives unwrapping, or using a raw collection type that JAXB cannot bind) with a JAXBDecoder.

Common situations: Using generic or wrapper return types with JAXB decoding, which JAXB cannot represent without an annotated root wrapper class.

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/11d0a4a4090abdd6. Report an issue: GitHub.

Appendix: source

Thrown at jaxb/src/main/java/feign/jaxb/JAXBDecoder.java:76

    this.jaxbContextFactory = jaxbContextFactory;
    this.namespaceAware = true;
  }

  private JAXBDecoder(Builder builder) {
    this.jaxbContextFactory = builder.jaxbContextFactory;
    this.namespaceAware = builder.namespaceAware;
  }

  @Override
  public Object decode(Response response, Type type) throws IOException {
    if (response.status() == 404 || response.status() == 204) return Util.emptyValueOf(type);
    if (response.body() == null) return null;
    while (type instanceof ParameterizedType) {
      ParameterizedType ptype = (ParameterizedType) type;
      type = ptype.getRawType();
    }
    if (!(type instanceof Class)) {
      throw new UnsupportedOperationException(
          "JAXB only supports decoding raw types. Found " + type);
    }

    try {
      SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
      /* Explicitly control sax configuration to prevent XXE attacks */
      saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
      saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
      saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
      saxParserFactory.setFeature(
          "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
      saxParserFactory.setNamespaceAware(namespaceAware);

      return jaxbContextFactory
          .createUnmarshaller((Class<?>) type)
          .unmarshal(
              new SAXSource(
                  saxParserFactory.newSAXParser().getXMLReader(),

View on GitHub (pinned to e2a1e27560)