apache/rocketmq · error · NullPointerException

machineRoomResolver is null

Error message

machineRoomResolver is null

What it means

Second constructor guard in AllocateMachineRoomNearby: the MachineRoomResolver (used to map consumers and queues to machine rooms) must not be null. Without it the strategy cannot group participants, so the constructor throws NullPointerException as a fail-fast contract violation.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/consumer/rebalance/AllocateMachineRoomNearby.java:48

 * specified.
 *
 * If any consumer is alive in a machine room, the message queue of the broker which is deployed in the same machine
 * should only be allocated to those. Otherwise, those message queues can be shared along all consumers since there are
 * no alive consumer to monopolize them.
 */
public class AllocateMachineRoomNearby extends AbstractAllocateMessageQueueStrategy {

    private final AllocateMessageQueueStrategy allocateMessageQueueStrategy;//actual allocate strategy
    private final MachineRoomResolver machineRoomResolver;

    public AllocateMachineRoomNearby(AllocateMessageQueueStrategy allocateMessageQueueStrategy,
        MachineRoomResolver machineRoomResolver) throws NullPointerException {
        if (allocateMessageQueueStrategy == null) {
            throw new NullPointerException("allocateMessageQueueStrategy is null");
        }

        if (machineRoomResolver == null) {
            throw new NullPointerException("machineRoomResolver is null");
        }

        this.allocateMessageQueueStrategy = allocateMessageQueueStrategy;
        this.machineRoomResolver = machineRoomResolver;
    }

    @Override
    public List<MessageQueue> allocate(String consumerGroup, String currentCID, List<MessageQueue> mqAll,
        List<String> cidAll) {

        List<MessageQueue> result = new ArrayList<>();
        if (!check(consumerGroup, currentCID, mqAll, cidAll)) {
            return result;
        }

        //group mq by machine room
        Map<String/*machine room */, List<MessageQueue>> mr2Mq = new TreeMap<>();
        for (MessageQueue mq : mqAll) {

View on GitHub (pinned to 293f588571)

Solutions

  1. Implement MachineRoomResolver (return a fixed room name for single-room deployments) and pass it
  2. If you do not need machine-room logic, drop AllocateMachineRoomNearby and use AllocateMessageQueueAveragely directly
  3. Verify DI wiring provides both constructor arguments

Example fix

// before
new AllocateMachineRoomNearby(new AllocateMessageQueueAveragely(), null);

// after
new AllocateMachineRoomNearby(new AllocateMessageQueueAveragely(),
    new MachineRoomResolver() {
        public String brokerDeployIn(MessageQueue mq) { return "DefaultRoom"; }
        public String consumerDeployIn(String clientIp) { return "DefaultRoom"; }
    });
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(resolver, "machineRoomResolver is null");
Objects.requireNonNull(delegate, "allocateMessageQueueStrategy is null");
new AllocateMachineRoomNearby(delegate, resolver);

Prevention

When it happens

Trigger: new AllocateMachineRoomNearby(strategy, null) — resolver omitted because the app has no machine-room awareness, or the resolver bean failed to construct.

Common situations: Copy-pasting the constructor call without implementing the MachineRoomResolver interface; DI setups where the resolver is an inner/anonymous bean that was never defined.

Related errors


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