[
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)