OpenFeign/feign · error · DecodeException

${e.toString()}

Error message

${e.toString()}

What it means

JAXBDecoder.decode catches JAXBException, ParserConfigurationException and SAXException while unmarshalling the response body via SAX and rethrows them as a Feign DecodeException whose message is e.toString(). It means XML parsing/unmarshalling of the HTTP response failed - typically malformed XML, a root element that does not match the target type, or a class not correctly mapped via JAXBContextFactory.

Solutions

  1. Inspect e.getCause() in the DecodeException to see the actual JAXB/SAX error and fix the XML or the type mapping.
  2. Verify the server returns well-formed XML matching the annotated return type (root element, namespaces).
  3. Ensure target DTOs carry @XmlRootElement/@XmlElement annotations and are registered with the JAXBContextFactory.
  4. Catch DecodeException in caller code and log status plus cause for diagnostics.

Example fix

// before
MyDto dto = api.get(); // throws DecodeException on bad XML
// after
try {
  MyDto dto = api.get();
} catch (DecodeException e) {
  logger.error("decode failed status=" + e.status(), e.getCause());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling
String ct = response.headers().getOrDefault("content-type", "").toLowerCase();
if (!ct.contains("xml")) throw new IllegalStateException("endpoint did not return XML: " + ct);

Try / catch

try {
  result = api.call();
} catch (DecodeException e) {
  Throwable c = e.getCause();
  if (c instanceof SAXException || c instanceof JAXBException) {
    // malformed XML or mapping mismatch; log and fall back
  } else { throw e; }
}

Prevention

When it happens

Trigger: decode() is invoked on a response whose body is not well-formed XML, or whose XML does not match the @XmlRootElement-annotated target type; also raised when SAX parser creation fails or the underlying input stream errors during unmarshal.

Common situations: Server returns an HTML error page instead of XML; response XML root element or namespaces don't match the declared return type; missing @XmlRootElement on the DTO causing JAXBException; response truncated by a proxy.

Related errors


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

Appendix: source

Thrown at jaxb-jakarta/src/main/java/feign/jaxb/JAXBDecoder.java:97

    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(),
                  new InputSource(response.body().asInputStream())));
    } catch (JAXBException | ParserConfigurationException | SAXException e) {
      throw new DecodeException(response.status(), e.toString(), response.request(), e);
    } finally {
      if (response.body() != null) {
        response.body().close();
      }
    }
  }

  public static class Builder {
    private boolean namespaceAware = true;
    private JAXBContextFactory jaxbContextFactory;

    /** Controls whether the underlying XML parser is namespace aware. Default is true. */
    public Builder withNamespaceAware(boolean namespaceAware) {
      this.namespaceAware = namespaceAware;
      return this;
    }

    public Builder withJAXBContextFactory(JAXBContextFactory jaxbContextFactory) {

View on GitHub (pinned to e2a1e27560)