apache/rocketmq · error · MQClientException

13

13

Error message

the message is null

What it means

Validators.checkMessage (called from producer.send paths) rejects a null Message object with MQClientException code 13 (MESSAGE_ILLEGAL). This is a pure client-side null check before topic/body validation runs.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/Validators.java:68

    public static void checkGroup(String group) throws MQClientException {
        if (UtilAll.isBlank(group)) {
            throw new MQClientException("the specified group is blank", null);
        }

        if (group.length() > GROUP_MAX_LENGTH) {
            throw new MQClientException(String.format("the specified group[%s] is longer than group max length: %s.", group, GROUP_MAX_LENGTH), null);
        }

        if (isTopicOrGroupIllegal(group)) {
            throw new MQClientException(String.format(
                    "the specified group[%s] contains illegal characters, allowing only %s", group,
                    "^[%|a-zA-Z0-9_-]+$"), null);
        }
    }

    public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer) throws MQClientException {
        if (null == msg) {
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message is null");
        }
        // topic
        Validators.checkTopic(msg.getTopic());
        Validators.isNotAllowedSendTopic(msg.getTopic());

        // body
        if (null == msg.getBody()) {
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message body is null");
        }

        if (0 == msg.getBody().length) {
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message body length is zero");
        }

        if (msg.getBody().length > defaultMQProducer.getMaxMessageSize()) {
            throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL,
                "the message body size over max value, MAX: " + defaultMQProducer.getMaxMessageSize());
        }

View on GitHub (pinned to 293f588571)

Solutions

  1. Guard the call site: only send when the constructed Message is non-null, or throw a domain-specific exception instead.
  2. Fix the upstream builder so it never returns null (return Optional<Message> and chain).
  3. Enable strict null checks / @NonNull annotations on the send wrapper.

Example fix

// before
Message m = buildMessage(event); // may return null
producer.send(m);

// after
Message m = buildMessage(event);
if (m != null) {
    producer.send(m);
}
Defensive patterns

Strategy: type-guard

Type guard

static boolean isSendable(Message msg) {
    return msg != null;
}

Try / catch

try {
    producer.send(msg);
} catch (MQClientException e) {
    if (e.getResponseCode() == ResponseCode.MESSAGE_ILLEGAL && "the message is null".equals(e.getMessage())) {
        // caller-side bug: fix message construction, do not retry
    }
}

Prevention

When it happens

Trigger: Calling producer.send(null) or producer.send(null, timeout) — typically when the calling code builds a message from a map/optional and the lookup returned null.

Common situations: Optional.map(...).orElse(null) feeding send(); a null returned from a builder when input is invalid; refactoring that removed a null branch.

Related errors


AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14). Data as JSON: /api/errors/53510633fd8ddfda. Report an issue: GitHub.