OpenFeign/feign · error · UnsupportedOperationException

SOAP only supports decoding raw types. Found

Error message

SOAP only supports decoding raw types. Found %s

What it means

The jakarta SOAP decoder can only unmarshal the response body into a raw class, because JAXB/SAJ unmarshalling requires a Class. Before decoding, it strips ParameterizedType wrappers (e.g. List<Foo>) to the raw type; if the type is still not a Class (e.g. a generic type variable or wildcard), it throws UnsupportedOperationException. Note generics like List<Foo> are partially handled by taking the raw type, but non-class types are rejected.

Solutions

  1. Change the Feign method return type to a concrete raw class (or List<ConcreteClass>, which unwraps to List's raw type) instead of a generic type variable or wildcard.
  2. If you need generics, build a dedicated interface per concrete type or supply a custom Decoder that resolves the type variable before delegating to SOAPDecoder.

Example fix

// before
<T> T getOrder();
// after
Order getOrder();
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

if (!isSoapDecodable(methodReturnType)) {
  throw new IllegalArgumentException("SOAP method return type must resolve to a raw Class");
}

Try / catch

try {
  return soapClient.call();
} catch (UnsupportedOperationException e) {
  if (e.getMessage() != null && e.getMessage().contains("SOAP only supports decoding raw types")) {
    // fix return type to a concrete class
  }
  throw e;
}

Prevention

When it happens

Trigger: Declaring a Feign interface method whose return type is not resolvable to a raw Class after unwrapping ParameterizedTypes — e.g. a generic type variable T, wildcard, or generic array — and calling that method so decode() runs on the response.

Common situations: Using a generic client interface with a type variable return type; declaring ResponseEntity-ish wrappers that are not simple parameterized types; copy-pasting a decoder config from the non-generic SOAP 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/c9b5ff089d78c450. Report an issue: GitHub.

Appendix: source

Thrown at soap-jakarta/src/main/java/feign/soap/SOAPDecoder.java:106

    this.useFirstChild = false;
  }

  private SOAPDecoder(Builder builder) {
    this.soapProtocol = builder.soapProtocol;
    this.jaxbContextFactory = builder.jaxbContextFactory;
    this.useFirstChild = builder.useFirstChild;
  }

  @Override
  public Object decode(Response response, Type type) throws IOException {
    if (response.status() == 404) 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(
          "SOAP only supports decoding raw types. Found " + type);
    }

    try {
      SOAPMessage message =
          MessageFactory.newInstance(soapProtocol)
              .createMessage(null, response.body().asInputStream());
      if (message.getSOAPBody() != null) {
        if (message.getSOAPBody().hasFault()) {
          throw new SOAPFaultException(message.getSOAPBody().getFault());
        }

        Unmarshaller unmarshaller = jaxbContextFactory.createUnmarshaller((Class<?>) type);

        if (this.useFirstChild) {
          return unmarshaller.unmarshal(message.getSOAPBody().getFirstChild());
        } else {
          return unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());

View on GitHub (pinned to e2a1e27560)