You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "shashank (Jira)" <ji...@apache.org> on 2026/10/02 01:38:00 UTC

[jira] [Created] (CAMEL-25250) camel-grpc - with the AGGREGATION or PROPAGATION consumer strategy a failed exchange is answered with its message body as a successful response instead of an error

shashank created CAMEL-25250:
--------------------------------

             Summary: camel-grpc - with the AGGREGATION or PROPAGATION consumer strategy a failed exchange is answered with its message body as a successful response instead of an error
                 Key: CAMEL-25250
                 URL: https://issues.apache.org/jira/browse/CAMEL-25250
             Project: Camel
          Issue Type: Bug
          Components: camel-grpc
            Reporter: shashank


For unary and server streaming calls, {{GrpcMethodHandler.handle}} ends the call with {{Status.INTERNAL}} when the exchange failed (CAMEL-14893; the description follows {{muteException}} since CAMEL-24478). Client streaming and bidirectional streaming calls go through the consumer strategy observers instead, and these never look at the exchange result:

* {{GrpcRequestAggregationStreamObserver.onCompleted}} (strategy {{AGGREGATION}}) sends {{exchange.getMessage().getBody()}} with {{onNext}} and then {{onCompleted}};
* {{GrpcRequestPropagationStreamObserver.onNext}} (strategy {{PROPAGATION}}, the default) sends the body of each exchange with {{onNext}}, and {{onCompleted}} completes the call.

So a route that fails after it built the response (a {{to(...)}} after the transformation, a validation, a database write) answers the client with a successful response, and the error stays on the server (it only goes to the consumer's exception handler). When the route fails before it built a response, the body is the request (or the list of requests), which the response marshaller cannot write; the call then fails with an unrelated error.

h3. Reproduction

{code:java}
from("grpc://localhost:0/org.apache.camel.component.grpc.PingPong?synchronous=true&consumerStrategy=AGGREGATION&muteException=false")
    .bean(new GrpcMessageBuilder(), "buildAggregatedPongResponse")   // List<PingRequest> -> PongResponse
    .throwException(CamelException.class, "GRPC Camel streaming exception message");
{code}

and the same with {{consumerStrategy=PROPAGATION}} and a bean that maps one {{PingRequest}} to a {{PongResponse}}. A client calling the client streaming method {{pingAsyncSync}} gets the {{PongResponse}} ({{pong_name: "PINGPONG"}}) and a normal completion; a unary call to the same failing route gets {{INTERNAL}}. A test with both strategies fails on main.

h3. Proposed fix

Both observers end the call with the same {{Status.INTERNAL}} error as the unary path when the exchange failed (shared helper {{GrpcMethodHandler.toStatusException}}, so {{muteException}} applies the same way). The propagation observer remembers the failure: the call is over, so later requests of the client are no longer routed and the response observer is not called again ({{onCompleted}} and {{onError}} of the client are still forwarded to the route when {{forwardOnCompleted}}/{{forwardOnError}} are set). A route that must keep a bidirectional stream open handles the exception ({{onException(...).handled(true)}}). The {{DELEGATION}} strategy is unchanged: the route controls the response observer there. With the fix the new test and the whole camel-grpc suite pass. Clients now get errors where they got responses, so the change gets an upgrade guide note.

Affected: 4.14.x, 4.18.x and main (same observers; 4.14.x has no {{muteException}}, so a backport there uses the exception message as the unary path does).

Duplicate check (2026-10-01): JIRA component camel-grpc (all 41 issues) and text "grpc" with "aggregation"/"propagation"/"streaming" and "exception": only CAMEL-14893 (unary calls) and CAMEL-24478. GitHub pull requests "grpc exception", "grpc streaming": none about the streaming strategies.

_Filed with Claude Code on behalf of allthingssecurity._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)