OpenFeign/feign · error · FeignException
reading
Error message
%s reading %s %s
What it means
In InvocationContext.decode, when the configured Decoder throws a RuntimeException (not a FeignException), it is wrapped as a DecodeException whose message is "%s reading %s %s" (configKey, status, original message); IOExceptions are converted via errorReading. This means a response was received but decoding its body into the method's return type failed.
Solutions
- Inspect the wrapped cause (e.getMessage()) for the exact parse/mapping failure.
- Register the correct decoder, e.g. Feign.builder().decoder(JacksonDecoder.create()) for JSON APIs.
- Compare the actual response payload against the DTO fields/types and update the model.
- Check the response Content-Type matches what the decoder expects.
Example fix
// before
Feign.builder().target(Api.class, url); // default decoder only handles String/byte[]
// after
Feign.builder()
.decoder(JacksonDecoder.create())
.target(Api.class, url); Defensive patterns
Strategy: try-catch
Validate before calling
// verify decoder matches the API media type before building the client
if (!apiProducesJson) throw new IllegalStateException("register JSON decoder"); Try / catch
try {
return api.getData();
} catch (DecodeException e) {
// log e.content() and cause to compare payload vs DTO; fall back or rethrow mapped error
} Prevention
- Register the decoder matching your API (Jackson/Gson) via Feign.builder().decoder(...)
- Keep DTOs in sync with the upstream response schema
- Confirm response Content-Type matches the decoder
- Capture the raw response body in logs at debug level for debugging decode failures
When it happens
Trigger: Decoder throws while parsing the body: malformed JSON, JSON not matching the target type, wrong Content-Type/charset, empty body for a non-void type, or a decoder bug.
Common situations: Server returns HTML error page where JSON expected; missing or wrong decoder configured (e.g. no Jackson decoder registered); response schema changed upstream; stale generated DTOs after API version change.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- reading
- StreamDecoder supports types other than stream. When type…
- Cannot decode type
- Cannot convert to type
- Not supported type
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/d7d675bce8452f95.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/feign/InvocationContext.java:127
}
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)