This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 85f839b6c fix(message): surface message-id lookup failures (#4525)
85f839b6c is described below

commit 85f839b6c35b108de0844e71c75bc3abeb73981d
Author: zmuxuny <[email protected]>
AuthorDate: Mon Sep 21 17:29:43 2026 +0800

    fix(message): surface message-id lookup failures (#4525)
    
    queryByMsgId conflated operational lookup failures with an absent message: 
both the primary viewMessage call and the decoded-offset fallback reduced 
errors to an empty result. Known absence (TOPIC_NOT_EXIST / NO_MESSAGE / 
QUERY_NOT_FOUND via MqResponseCodes) still returns an empty list; any other 
failure now raises BusinessException(502) so the console reports the lookup 
error instead of "no such message".
    
    Fixes #4524
---
 .../provider/apache/RocketMQMessageProvider.java   | 69 ++++++++++++++++++----
 .../apache/RocketMQMessageProviderTest.java        | 33 ++++++++++-
 2 files changed, 90 insertions(+), 12 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
index 4b42fccaf..d17bb88ec 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
@@ -145,17 +145,30 @@ public class RocketMQMessageProvider implements 
MessageProvider {
 
     private List<MessageRecordVO> queryByMsgId(DefaultMQAdminExt adminExt, 
String topic, String msgId) {
         MessageExt messageExt = null;
+        Exception primaryFailure = null;
         if (StringUtils.hasText(topic)) {
+            if (!BrokerTopologyGuards.isWithinKnownBrokerTopology(adminExt, 
msgId)) {
+                return Collections.emptyList();
+            }
             try {
-                if (BrokerTopologyGuards.isWithinKnownBrokerTopology(adminExt, 
msgId)) {
-                    messageExt = adminExt.viewMessage(topic, msgId);
-                }
+                messageExt = adminExt.viewMessage(topic, msgId);
             } catch (Exception e) {
+                if (isMessageLookupAbsent(e)) {
+                    return Collections.emptyList();
+                }
+                primaryFailure = e;
                 log.warn("viewMessage(topic={}, msgId={}) failed: {}", topic, 
msgId, e.getMessage());
             }
         }
         if (messageExt == null) {
-            messageExt = viewMessageByOffsetId(adminExt, topic, msgId);
+            OffsetMessageLookup lookup = lookupMessageByOffsetId(adminExt, 
topic, msgId);
+            messageExt = lookup.message();
+            if (messageExt == null && lookup.failure() != null) {
+                throw messageLookupFailure(lookup.failure());
+            }
+        }
+        if (messageExt == null && primaryFailure != null) {
+            throw messageLookupFailure(primaryFailure);
         }
         if (messageExt == null) {
             return Collections.emptyList();
@@ -168,20 +181,50 @@ public class RocketMQMessageProvider implements 
MessageProvider {
      * msgId, then querying that broker directly.
      */
     private MessageExt viewMessageByOffsetId(DefaultMQAdminExt adminExt, 
String topic, String msgId) {
+        OffsetMessageLookup lookup = lookupMessageByOffsetId(adminExt, topic, 
msgId);
+        if (lookup.failure() != null) {
+            log.warn("viewMessage by decoded offset id failed for msgId={}: 
{}",
+                    msgId, lookup.failure().getMessage());
+        }
+        return lookup.message();
+    }
+
+    private OffsetMessageLookup lookupMessageByOffsetId(DefaultMQAdminExt 
adminExt, String topic, String msgId) {
+        MessageId messageId;
+        try {
+            messageId = MessageDecoder.decodeMessageId(msgId);
+        } catch (Exception exception) {
+            return OffsetMessageLookup.empty();
+        }
         try {
-            MessageId messageId = MessageDecoder.decodeMessageId(msgId);
             String brokerAddr = 
BrokerTopologyGuards.validatedBrokerAddr(adminExt, msgId, messageId);
             if (!StringUtils.hasText(brokerAddr)) {
-                return null;
+                return OffsetMessageLookup.empty();
             }
-            return adminExt.getDefaultMQAdminExtImpl()
+            MessageExt message = adminExt.getDefaultMQAdminExtImpl()
                     .getMqClientInstance()
                     .getMQClientAPIImpl()
                     .viewMessage(brokerAddr, topic, messageId.getOffset(), 
VIEW_MESSAGE_TIMEOUT_MILLIS);
-        } catch (Exception e) {
-            log.warn("viewMessage by decoded offset id failed for msgId={}: 
{}", msgId, e.getMessage());
-            return null;
+            return new OffsetMessageLookup(message, null);
+        } catch (Exception exception) {
+            if (isMessageLookupAbsent(exception)) {
+                return OffsetMessageLookup.empty();
+            }
+            return new OffsetMessageLookup(null, exception);
+        }
+    }
+
+    private static boolean isMessageLookupAbsent(Throwable throwable) {
+        return MqResponseCodes.hasResponseCode(throwable, 
ResponseCode.TOPIC_NOT_EXIST,
+                ResponseCode.NO_MESSAGE, ResponseCode.QUERY_NOT_FOUND);
+    }
+
+    private static BusinessException messageLookupFailure(Throwable throwable) 
{
+        String message = throwable.getMessage();
+        if (message == null || message.isBlank()) {
+            message = throwable.getClass().getSimpleName();
         }
+        return new BusinessException(502, "Failed to query message by id: " + 
message);
     }
 
     private MessageQueryResult queryByKey(DefaultMQAdminExt adminExt, String 
topic, String key,
@@ -863,6 +906,12 @@ public class RocketMQMessageProvider implements 
MessageProvider {
         return (value & 0xC0) == 0x80;
     }
 
+    private record OffsetMessageLookup(MessageExt message, Throwable failure) {
+        private static OffsetMessageLookup empty() {
+            return new OffsetMessageLookup(null, null);
+        }
+    }
+
     private record DisplayBody(String value, String encoding, boolean 
truncated) {
     }
 
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
index ba3d0acfa..37654fec4 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
@@ -385,6 +385,22 @@ class RocketMQMessageProviderTest {
         verify(clientApi).viewMessage("172.30.10.100:10911", "TopicA", 
27521713L, 3000L);
     }
 
+    @Test
+    void queryByMsgIdSurfacesOffsetFallbackFailureTest() throws Exception {
+        String msgId = "AC1E0A6400002A9F0000000001A3F2B1";
+        MQClientAPIImpl clientApi = mockOffsetLookupClient();
+        when(adminExt.viewMessage("TopicA", msgId))
+                .thenThrow(new IllegalStateException("primary lookup failed"));
+        when(clientApi.viewMessage("172.30.10.100:10911", "TopicA", 27521713L, 
3000L))
+                .thenThrow(new IllegalStateException("broker unavailable"));
+
+        assertThatThrownBy(() -> provider.queryMessages(
+                "instance-a", "TopicA", msgId, null, null, 100L, 200L))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("Failed to query message by id: broker 
unavailable")
+                .satisfies(error -> assertThat(((BusinessException) 
error).getCode()).isEqualTo(502));
+    }
+
     @Test
     void queryByMsgIdIgnoresUnrelatedTimeBounds() throws Exception {
         MessageExt message = new MessageExt();
@@ -441,9 +457,10 @@ class RocketMQMessageProviderTest {
     }
 
     @Test
-    void queryByMsgIdPassesNonOffsetIdsThroughToViewMessage() throws Exception 
{
+    void queryByMsgIdTreatsKnownNonOffsetAbsenceAsEmptyTest() throws Exception 
{
         when(adminExt.viewMessage("TopicA", "uniq-key-1"))
-                .thenThrow(new IllegalStateException("unique key lookup 
handled by MQAdminImpl"));
+                .thenThrow(new MQClientException(ResponseCode.QUERY_NOT_FOUND,
+                        "query message by key finished, but no message"));
 
         List<MessageRecordVO> result = provider.queryMessages(
                 "instance-a", "TopicA", "uniq-key-1", null, null, 100L, 200L);
@@ -453,6 +470,18 @@ class RocketMQMessageProviderTest {
         verify(adminExt, never()).examineBrokerClusterInfo();
     }
 
+    @Test
+    void queryByMsgIdSurfacesNonOffsetLookupFailureTest() throws Exception {
+        when(adminExt.viewMessage("TopicA", "uniq-key-failure"))
+                .thenThrow(new IllegalStateException("nameserver 
unavailable"));
+
+        assertThatThrownBy(() -> provider.queryMessages(
+                "instance-a", "TopicA", "uniq-key-failure", null, null, 100L, 
200L))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("Failed to query message by id: nameserver 
unavailable")
+                .satisfies(error -> assertThat(((BusinessException) 
error).getCode()).isEqualTo(502));
+    }
+
     @Test
     void queryByMsgIdStillViewsMessagesInsideKnownTopology() throws Exception {
         String msgId = MessageDecoder.createMessageId(

Reply via email to