[
https://issues.apache.org/jira/browse/CAMEL-25660?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18127106#comment-18127106
]
Andrea Cosentino commented on CAMEL-25660:
------------------------------------------
PR: https://github.com/apache/camel/pull/27834
Both halves: the reason and description are capped (1024 / 8192 characters,
with a trailing ellipsis so a cut value is recognisable), and a rejected
dead-letter request is reported through the consumer exception handler instead
of escaping {{onFailure}}.
Revert-checked separately - dropping the bounding fails the bounds test on all
3 runs; dropping the guard lets the rejection propagate out of {{onFailure}} on
all 3. camel-azure-servicebus: 76 tests, 8 skipped, green.
{{onComplete}} has the same unguarded shape around
{{messageContext.complete()}} and was left alone, as it is a different failure
(a lost lock rather than an oversized payload) and deserves its own decision.
_Claude Code on behalf of
> camel-azure-servicebus - dead-lettering builds unbounded reason and
> description from the exception, and a failure to dead-letter is not caught
> ----------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25660
> URL: https://issues.apache.org/jira/browse/CAMEL-25660
> Project: Camel
> Issue Type: Bug
> Components: camel-azure-servicebus
> Reporter: Andrea Cosentino
> Assignee: Andrea Cosentino
> Priority: Major
>
> h3. Summary
> With {{enableDeadLettering=true}} in PEEK_LOCK mode,
> {{ServiceBusConsumer.ConsumerOnCompletion.onFailure}} dead-letters the
> message with a reason and a description built from the route's exception. Two
> problems:
> # The call is not guarded, so a rejected dead-letter request escapes
> {{onFailure}} and the message is never dead-lettered at all.
> # Neither field is bounded, so Camel does nothing to keep the message under
> the size quota that Azure's own documentation warns about for exactly this
> practice.
> h3. The unguarded call
> {code:java}
> try {
> ...
> messageContext.deadLetter(deadLetterOptions);
> ...
> } finally {
> pendingExchanges.decrementAndGet();
> }
> {code}
> There is no {{catch}}. If the broker rejects the request, the exception
> leaves {{onFailure}} into the Azure SDK's processor callback, and nothing
> reports it through the consumer's configured {{ExceptionHandler}}. The
> message stays locked, the lock expires, Service Bus redelivers it, the route
> fails the same way - and this repeats until {{maxDeliveryCount}} is reached,
> at which point the broker dead-letters it itself with reason
> {{MaxDeliveryCountExceeded}}. The outcome is that the diagnostics
> {{enableDeadLettering}} exists to provide are exactly what gets lost, and the
> exchange is processed several more times than intended.
> {{onComplete}} has the same unguarded shape around
> {{messageContext.complete()}}, which is worth deciding on at the same time.
> h3. The unbounded fields
> {code:java}
> deadLetterOptions.setDeadLetterReason(
> String.format("%s: %s", cause.getClass().getName(),
> cause.getMessage()));
> deadLetterOptions.setDeadLetterErrorDescription(Arrays.stream(cause.getStackTrace())
> .map(StackTraceElement::toString)
> .collect(Collectors.joining("\n")));
> {code}
> To be clear, the *content* here is what Azure asks for. The dead-letter queue
> documentation says:
> {quote}We recommend that you include the type of the exception in the
> {{DeadLetterReason}} and the stack trace of the exception in the
> {{DeadLetterDescription}} as it makes it easier to troubleshoot the cause of
> the problem resulting in messages being dead-lettered. It might result in
> some messages exceeding the 256 KB quota limit for the Standard tier of Azure
> Service Bus.{quote}
> So the component follows the recommendation but not the caveat: a full Camel
> stack trace, with error-handler and processor frames, is routinely several
> thousand characters, and {{cause.getMessage()}} is itself unbounded (a
> database error quoting the statement, a validation report). Nothing truncates
> either one, and {{com.azure.messaging.servicebus.models.DeadLetterOptions}}
> does no client-side length validation (checked against
> azure-messaging-servicebus 7.17.16), so the broker is what rejects it -
> landing on problem 1 above.
> h3. Suggested fix
> Bound both fields, keeping the recommended content but capping it, and guard
> the dead-letter call so a rejection is reported through the exception handler
> rather than escaping {{onFailure}}. The head of a stack trace is the useful
> part; the tail is error-handler frames.
> h3. Evidence
> * Verified by reading the component on main: no {{catch}} around
> {{deadLetter}}, neither field bounded.
> * Verified that {{DeadLetterOptions}} has no length validation in the SDK.
> * The 256 KB Standard-tier caveat is quoted from Microsoft's dead-letter
> queue documentation above.
> * *Not* reproduced against a live namespace. The exact payload size at which
> the broker rejects the request has not been measured, and the documentation
> gives a message-size quota rather than a per-field limit.
> h4. Correction to the original description
> The first version of this issue claimed a documented 4096 limit on the
> dead-letter reason and description. That came from the .NET
> {{DeadLetterMessageAsync}} API reference and is *not* corroborated by the
> dead-letter queue page or the Service Bus quotas page, so I am retracting it.
> The documented constraint is the 256 KB message-size quota on the Standard
> tier, quoted above. The unguarded call - the more serious half - is
> unaffected either way, since it is verified in Camel's own code.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)