[ 
https://issues.apache.org/jira/browse/CAMEL-24138?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen reassigned CAMEL-24138:
-----------------------------------

    Assignee: Claus Ibsen

> camel-core - Splitter errorThreshold/maxFailedRecords: failure tracker leaks 
> into nested splits and silently swallows their failures
> ------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24138
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24138
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core, eip
>    Affects Versions: 4.22.0
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Critical
>         Attachments: SplitterNestedFailureTrackerLeakIssueTest.java
>
>
> The new {{errorThreshold}}/{{maxFailedRecords}} options (CAMEL-23264, 
> unreleased 4.22.0-SNAPSHOT) store the splitter's {{SplitFailureTracker}} as a 
> plain exchange property ({{CamelSplitFailureTracker}}, 
> {{Splitter.java:210}}). Exchange properties are copied into every 
> sub-exchange by {{createCorrelatedCopy}}, so the tracker *leaks into any 
> nested splitter* running inside the outer split. The inner splitter's 
> {{shouldContinueOnFailure}} looks the tracker up on _its_ input exchange:
> {code:java}
> SplitFailureTracker tracker = original.getProperty(SPLIT_FAILURE_TRACKER, 
> SplitFailureTracker.class);
> if (tracker == null) {
>     return super.shouldContinueOnFailure(subExchange, original, index);   // 
> normal behavior
> }
> tracker.recordFailure(index, subExchange.getException());
> // the inner splitter has maxFailedRecords == 0 and errorThreshold == 0, so 
> both checks are skipped
> ...
> subExchange.setException(null);    // <-- inner failure silently cleared
> return true;
> {code}
> Because the _inner_ splitter instance has no thresholds configured, both 
> threshold checks are skipped and it unconditionally clears the exception of 
> its own failed sub-items. Consequences:
> # Inner split failures no longer propagate — the inner split (and therefore 
> the outer item) *succeeds silently* even though items failed. The outer 
> {{maxFailedRecords}}/{{errorThreshold}} never trips.
> # Inner failures are recorded into the *outer* tracker with *inner* indexes, 
> corrupting {{SplitResult}} ({{failureCount}} can exceed {{totalItems}}, 
> making {{getSuccessCount()}} negative).
> *Reproducer (attached, fails on main):* 
> {{SplitterNestedFailureTrackerLeakIssueTest}} — outer 
> {{split(body()).maxFailedRecords(1)}} around a plain inner {{split(body())}} 
> whose item throws; the exchange completes without an exception instead of 
> aborting:
> {noformat}
> org.opentest4j.AssertionFailedError: Inner split failure was silently 
> swallowed by the leaked outer failure tracker ==> expected: not <null>
> {noformat}
> Suggested fix direction: don't discover the tracker via an inherited exchange 
> property — key it per-processor instance (like the {{AGGREGATION_STRATEGY}} 
> map keyed by processor), or only honor the tracker when {{this}} splitter 
> actually has thresholds configured ({{errorThreshold > 0 || maxFailedRecords 
> > 0}}).
> Since CAMEL-23264 is unreleased, this can still be fixed before 4.22.0 ships.
> _Filed by Claude Code on behalf of Federico Mariani (fmariani)_



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

Reply via email to