apache/rocketmq · error · MQClientException
208
208
Error message
query message by id finished, but no message.
What it means
Thrown by MQAdminImpl.viewMessage(topic, msgId) with response code NO_MESSAGE (208) when MessageDecoder.decodeMessageId(msgId) fails to parse the string into a MessageId (broker address + offset). Despite the wording, this is a malformed-msgId parse failure on the client, not a broker query that came back empty — the decode exception is swallowed and this MQClientException is raised instead.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/MQAdminImpl.java:273
if (brokerAddr != null) {
try {
return this.mQClientFactory.getMQClientAPIImpl().getEarliestMsgStoretime(brokerAddr, mq, timeoutMillis);
} catch (Exception e) {
throw new MQClientException("Invoke Broker[" + brokerAddr + "] exception", e);
}
}
throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null);
}
public MessageExt viewMessage(String topic, String msgId)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MessageId messageId;
try {
messageId = MessageDecoder.decodeMessageId(msgId);
} catch (Exception e) {
throw new MQClientException(ResponseCode.NO_MESSAGE, "query message by id finished, but no message.");
}
return this.mQClientFactory.getMQClientAPIImpl().viewMessage(NetworkUtil.socketAddress2String(messageId.getAddress()),
topic, messageId.getOffset(), timeoutMillis);
}
public QueryResult queryMessage(String topic, String key, int maxNum, long begin,
long end) throws MQClientException,
InterruptedException {
return queryMessage(null, topic, key, maxNum, begin, end, false, MessageConst.INDEX_KEY_TYPE, null);
}
public QueryResult queryMessageByUniqKey(String topic, String uniqKey, int maxNum, long begin, long end)
throws MQClientException, InterruptedException {
return queryMessage(null, topic, uniqKey, maxNum, begin, end, true, MessageConst.INDEX_UNIQUE_TYPE, null);
}
public QueryResult queryMessageByUniqKey(String clusterName, String topic, String uniqKey, int maxNum, long begin,
long end)View on GitHub (pinned to 293f588571)
Solutions
- Ensure msgId is a valid offset message id obtained from SendResult.getMsgId() or MessageExt.getMsgId() from the same client version
- To look up by unique key instead, use queryMessageByUniqKey(topic, uniqKey, ...) which queries the index
- If ids come from a newer producer, upgrade the client jar so decodeMessageId understands the id format
- Validate format before calling: 32 hex chars (or 64 with total-length field) for the installed client version
- Check for whitespace/linebreaks accidentally included when ids are copied from logs
Example fix
// before: uniqKey mistaken for msgId
MessageExt msg = adminExt.viewMessage("T", "user-order-12345"); // decode fails -> 208
// after: query by unique key
QueryResult r = adminExt.queryMessageByUniqKey("T", "user-order-12345", 1, 0, Long.MAX_VALUE);
MessageExt msg = r.getMessageList().get(0); Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern MSG_ID = Pattern.compile("^[0-9a-fA-F]{32,64}$");
boolean isOffsetMsgId(String s) { return s != null && MSG_ID.matcher(s).matches(); }
if (isOffsetMsgId(msgId)) { adminExt.viewMessage(topic, msgId); }
else { adminExt.queryMessageByUniqKey(topic, msgId, 1, 0, Long.MAX_VALUE); } Try / catch
try {
MessageExt m = adminExt.viewMessage(topic, msgId);
} catch (MQClientException e) {
if (e.getResponseCode() == ResponseCode.NO_MESSAGE) {
// msgId unparseable: fall back to uniq-key query
} else throw e;
} Prevention
- Store both msgId and uniqKey when producing so lookups have a fallback path
- Keep producer and admin client versions aligned so id formats match
- Trim ids copied from logs before use
When it happens
Trigger: Calling viewMessage(topic, msgId) with a string that is not a valid RocketMQ offset message id: wrong length, non-hex characters, null, or passing a business uniqKey (like a KEY property or generated UUID) where the 32-char offset msgId is required. Client-side only: the broker is never contacted when this fires.
Common situations: Passing SendResult.getMsgId() from a NEW API version into an OLD client whose decodeMessageId expects the total-length header (version incompatibility); confusing the unique key with the message id; truncated ids from logs or user input.
Related errors
- the specified group is blank
- the specified group[%s] is longer than group max length: %s.
- the specified group[%s] contains illegal characters, allowin
- authentication credential length is incorrect, actual length
- username can not be blank
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/076c4a5a13270fbe.
Report an issue: GitHub.