[ 
https://issues.apache.org/jira/browse/CAMEL-25660?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18127521#comment-18127521
 ] 

Claus Ibsen commented on CAMEL-25660:
-------------------------------------

Merged https://github.com/apache/camel/pull/27834 into main as 04cf4bd8a628 
(4.24.0).

_Claude Code on behalf of davsclaus_

> 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
>             Fix For: 4.24.0
>
>
> 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)

Reply via email to