f/error-as-a-value-even-when-error-occurs: init - #3559
Draft
ihsansfd wants to merge 1 commit into
Draft
Conversation
…o return error bodies as values instead of throwing
Feign hands every non-2xx response to the ErrorDecoder and throws, so a
service that describes its failures in the response body rather than by
status alone cannot reach that body from a Feign client. The workarounds
are declaring Response as the return type and decoding by hand, or
writing a ResponseInterceptor that skips the chain.
BaseBuilder#decodeErrorResponses() makes Feign decode the error body
into the method's declared return type and return it, rather than
throwing. The signature is the declaration of what an error body should
decode to, so no type is configured on the builder.
The flag engages only when all of the following hold, so the default
behaviour is untouched everywhere else:
- the status is >= 400. 3xx stays with RedirectionInterceptor.
- the decoder accepts the response, via PredicatedDecoder#canDecode,
so a JSON decoder is not handed an HTML error page from a proxy.
- the ErrorDecoder did not classify the response as retryable, so
Retryer keeps working on 503/Retry-After as it does today.
- the body actually decodes, otherwise the ErrorDecoder's exception is
thrown with the decode failure attached as suppressed.
The flag applies to every method on the client. It deliberately does not
check that the return type is one an error body makes sense as: most
decoders ignore unknown properties, so an error body decodes into an
unrelated type and yields an all-null object rather than failing, which
makes such a check unreliable. This is documented on the builder method,
with the guidance to use a separate client for methods that should keep
throwing.
The body is buffered once, since both the ErrorDecoder and the decoder
read it and a response body is not generally replayable. This adds no
memory exposure: DefaultErrorDecoder already reads the whole body to
build its message on every non-2xx response.
The response passed to the decoder has its status rewritten to 200.
JacksonDecoder, Jackson3Decoder and OptionalDecoder all short-circuit
404 and 204 to an empty value without reading the body, which would
discard the very body being asked for. Doing it here rather than in each
decoder also covers third-party decoders. TypedResponse is still built
from the real response, so its status() stays truthful.
Because the logic lives in InvocationContext#proceed, AsyncFeign gets
the same behaviour. The new ResponseHandler and AsyncResponseHandler
constructors are overloads, so the existing ones are unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJJJkfmVGccG7XPEeGFosm
ihsansfd
force-pushed
the
f/error-as-a-value-even-when-error-occurs
branch
from
September 5, 2026 16:50
445782b to
ea9a37e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#2944