OpenFeign/feign · error · DecodeException
${e.getMessage()}
Error message
${e.getMessage()} What it means
Thrown as a DecodeException wrapping the original decoder failure when the configured Decoder throws a non-Feign RuntimeException while deserializing the response body into the declared return type. It fires in InvocationContext.decode after the HTTP call succeeded, meaning the response arrived but could not be mapped — commonly a JSON/POJO mismatch (unknown properties, wrong type shape) or a decoder misconfiguration for the method's return Type.
Solutions
- Verify the interface method's return type matches the actual response body structure (field names, nesting, generics)
- Configure the underlying codec (e.g., Jackson ObjectMapper) to match the payload, or use a lenient/fail-safe setting if appropriate
- Ensure the correct Decoder is installed for the response content type (e.g., Jackson vs Gson)
- Catch DecodeException at the call site to distinguish transport success from deserialization failure
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at core/src/main/java/feign/InvocationContext.java:125 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/1b16f6f970beb1d2.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/feign/InvocationContext.java:125
if (!shouldDisconnectResponseBody) {
return response;
}
try {
final byte[] bodyData = Util.toByteArray(response.body().asInputStream());
return response.toBuilder().body(bodyData).build();
} finally {
ensureClosed(response.body());
}
}
private Object decode(Response response, Type returnType) {
try {
return decoder.decode(response, returnType);
} catch (final FeignException e) {
throw e;
} catch (final RuntimeException e) {
throw new DecodeException(response.status(), e.getMessage(), response.request(), e);
} catch (IOException e) {
throw errorReading(response.request(), response, e);
}
}
private Exception decodeError(String methodKey, Response response) {
try {
return errorDecoder.decode(methodKey, response);
} finally {
ensureClosed(response.body());
}
}
private boolean isVoidType(Type returnType) {
return returnType == Void.class
|| returnType == void.class
|| returnType.getTypeName().equals("kotlin.Unit");
}View on GitHub (pinned to e2a1e27560)