shashank created CAMEL-26434:
--------------------------------

             Summary: camel-core - doTry: after a route called from the doTry 
failed unhandled, a route called from the doCatch cannot handle its own failure 
with its error handler
                 Key: CAMEL-26434
                 URL: https://issues.apache.org/jira/browse/CAMEL-26434
             Project: Camel
          Issue Type: Bug
          Components: camel-core
            Reporter: shashank
            Assignee: shashank


Found while working on CAMEL-26333 (apache/camel#28756), from a question in its 
review.

When the {{doTry}} block calls a route (such as with {{direct}}) that fails 
*unhandled* (default error handler, no {{onException}}), that route's error 
handler marks the exchange as failure handled 
({{ExchangeExtension.isFailureHandled() == true}}, 
{{errorHandlerHandled=false}}) before the exception goes back to the caller. 
The {{doCatch}} then catches the exception, but {{CatchProcessor}} only clears 
the exception, not that mark. A route called from the {{doCatch}} that fails 
can then not apply its own error handler: {{RedeliveryErrorHandler.isDone}} 
treats an exchange that is failure handled as done, so neither its dead letter 
channel nor its handled {{onException}} run, and the exchange fails with that 
route's exception.

When the {{doTry}} block fails in the same route (no error handler involved, as 
doTry children are not wrapped in the route error handler), the same route 
called from the {{doCatch}} handles its failure as expected.

{code:java}
// the doTry calls a route that fails unhandled
from("direct:viaCallee")
    .doTry().to("direct:failing")
    
.doCatch(IllegalArgumentException.class).to("mock:catch").to("direct:dlcRoute")
    .end()
    .to("mock:after");
// control: the doTry fails in the same route
from("direct:inRoute")
    .doTry().throwException(new IllegalArgumentException("in route"))
    
.doCatch(IllegalArgumentException.class).to("mock:catch").to("direct:dlcRoute")
    .end()
    .to("mock:after");

from("direct:failing").throwException(new IllegalArgumentException("callee"));
from("direct:dlcRoute").errorHandler(deadLetterChannel("mock:dead").redeliveryDelay(0))
    .throwException(new IOException("in catch"));
// direct:viaCalleeOnException and direct:inRouteOnException: as above, with 
.to("direct:onExceptionRoute") in the doCatch
from("direct:onExceptionRoute")
    .onException(IOException.class).handled(true).to("mock:handled").end()
    .throwException(new IOException("in catch"));
{code}

On main (baaf532, 2026-10-31), with a JUnit test ({{ContextTestSupport}}, the 
two failing cases failed on all three surefire runs):

||send||doCatch calls||exception of the exchange||mock:dead||mock:handled||
|direct:viaCallee|dead letter channel route|{{IOException: in catch}}|0|0|
|direct:inRoute (control)|dead letter channel route|none|1|0|
|direct:viaCalleeOnException|handled onException route|{{IOException: in 
catch}}|0|0|
|direct:inRouteOnException (control)|handled onException route|none|0|1|

In the two failing cases the exchange is {{failureHandled=true}}, 
{{errorHandlerHandled=false}} when it comes back.

Expected: a route called from a {{doCatch}} handles (or continues) its own 
failure with its error handler, whether the {{doTry}} failed in the same route 
or in a route it called.

*Proposal*
* Clear the failure handled mark (and {{errorHandlerHandled}}, if set) when the 
{{doCatch}} takes over the exception in {{CatchProcessor}}, as CAMEL-26333 does 
around the {{doFinally}} block in {{FinallyProcessor}}, and check that the 
caller still behaves as before after the {{doCatch}} (it continues after the 
{{doTry}}, as the exception is caught). The related history is CAMEL-2577 and 
CAMEL-7275 (no nested error handlers for the children of doTry), which this 
does not change: the routes called from the {{doCatch}} have error handlers of 
their own.
* Tests: the four cases above, plus a nested {{doTry}} and an asynchronous 
callee.

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to