apache/rocketmq · error · MQClientException
The consumer service state not OK, {serviceState}
Error message
The consumer service state not OK, {serviceState} What it means
makeSureStateOK() is called before state-sensitive consumer operations (e.g. pull/pop message paths) and throws unless the consumer's serviceState is RUNNING. It protects internal APIs from being used on a consumer that has not completed start() or has already been shutdown().
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java:678
}
if (msgFoundList.size() != msgListFilterAgain.size()) {
for (MessageExt msg : msgFoundList) {
if (!msgListFilterAgain.contains(msg)) {
ackAsync(msg, this.groupName());
}
}
}
popResult.setMsgFoundList(msgListFilterAgain);
}
return popResult;
}
private void makeSureStateOK() throws MQClientException {
if (this.serviceState != ServiceState.RUNNING) {
throw new MQClientException("The consumer service state not OK, "
+ this.serviceState
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),
null);
}
}
void executePullRequestLater(final PullRequest pullRequest, final long timeDelay) {
this.mQClientFactory.getPullMessageService().executePullRequestLater(pullRequest, timeDelay);
}
public boolean isPause() {
return pause;
}
public void setPause(boolean pause) {
this.pause = pause;
}
View on GitHub (pinned to 293f588571)
Solutions
- Ensure consumer.start() completes before any message operations; check for exceptions from start()
- Do not reuse a DefaultMQPushConsumer after shutdown(); create a fresh instance instead
- If start() previously failed, inspect the earlier exception — this state error is only a symptom
- Delay shutdown until all in-flight consumer API calls have drained (e.g. during graceful application stop)
Example fix
// before
DefaultMQPushConsumer c = new DefaultMQPushConsumer("g");
c.subscribe("t", "*");
c.shutdown();
c.fetchSubscribeMessageQueues("t"); // state is SHUTDOWN_ALREADY
// after
DefaultMQPushConsumer c = new DefaultMQPushConsumer("g");
c.subscribe("t", "*");
c.start();
try {
c.fetchSubscribeMessageQueues("t");
} finally {
c.shutdown();
}
// any later need: construct a new consumer instance Defensive patterns
Strategy: try-catch
Validate before calling
// guard state before calling state-sensitive APIs
import org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl; // internal: prefer tracking lifecycle in your own wrapper
if (!started.get()) throw new IllegalStateException("consumer not started"); Try / catch
try {
consumer.fetchSubscribeMessageQueues(topic);
} catch (MQClientException e) {
if (e.getMessage().contains("service state not OK")) {
// consumer is stopped/failed: reinitialize or skip, do not blindly retry
reinitConsumer();
} else throw e;
} Prevention
- Model consumer lifecycle explicitly (NEW -> STARTED -> STOPPED) in your wrapper class
- Never share a consumer across start/shutdown cycles; recreate instances
- Drain in-flight calls before shutdown during graceful stop
When it happens
Trigger: Invoking message-population APIs (such as popMessage-related paths guarded by makeSureStateOK) before consumer.start() finished, after consumer.shutdown(), or while start() failed midway and left the state as CREATE_JUST/START_FAILED.
Common situations: Reusing a consumer instance after shutdown(); calling consumer methods from a thread before start() returned; a previous start() failure (e.g. duplicate consumer group) left the object in a non-RUNNING state; calling shutdown() during application undeploy and then issuing requests.
Related errors
- The PushConsumer service state not OK, maybe started once, {
- The consumer not running, please start it first.
- Subscribe and assign are mutually exclusive.
- The PullConsumer service state not OK, maybe started once,
- setAssignTag only can be called before start.
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/ae35537e260bc274.
Report an issue: GitHub.