Repository navigation
[Java Agent] NPE in rocketMQ-5.x-plugin OnSuccessInterceptor when rocketmq-client 5.x wraps async-send callbacks (BackpressureSendCallBack) #14189
Search before asking
Apache SkyWalking agent version9.8.0 (latest release). The affected code is byte-for-byte identical on Target / library versions
What happenedUnder load (high-frequency async sends), the agent log continuously shows two paired ERRORs on the RocketMQ client callback threads: The exceptions are swallowed by Root causeThree facts combine into a guaranteed NPE whenever one send produces a nested chain of two
Then, on callback execution:
The observed log sequence maps exactly onto this nesting (outer callback runs first, delegates to inner in the same call stack):
Note the log signature fits only this explanation: the inner callback reports a before failure, the outer reports an after failure, and there is no outer before error — any other failure mode would produce a different pair. Impact
ReproduceAttach agent 9.8.0 to any service using DefaultMQProducer producer = new DefaultMQProducer("demo");
producer.start();
producer.send(msg, new SendCallback() { // wrapped internally by BackpressureSendCallBack
public void onSuccess(SendResult r) { }
public void onException(Throwable t) { }
}, 3000);With msgTrace enabled (as with the Spring Cloud Stream RocketMQ binder defaults), the Suggested fix
Additional contextThe 4.x plugin had a sibling problem with |
Replies: 1 comment
|
Thanks for the detailed report and analysis. Confirmed, and fixed in apache/skywalking-java#848, which will ship in 9.9.0.
On impact: when the callback thread has no other active span, which is the usual case, the wrapper's span is still finished and reported with the right parent, so the trace data stays intact. What you see is the two ERRORs per callback. A trace would only be corrupted if the callback thread already had an active span. While checking newer RocketMQ versions, the same PR also fixes two issues in the |
Thanks for the detailed report and analysis. Confirmed, and fixed in apache/skywalking-java#848, which will ship in 9.9.0.
send(..., SendCallback, ...)overloads wrap the callback inBackpressureSendCallBack, whether backpressure is enabled or not. So any async send with a callback is affected, not only msgTrace.MQClientAPIImpl#sendMessageand gets theSendCallBackEnhanceInfo. Your sequence is right: the inner callback'sbeforeMethodthrows the NPE, its unconditionalstopSpan()pops the wrapper's span, and the wrapper'safterMethodthrows the second NPE on the empty context.onExceptionalready handles the missing info.