apache/rocketmq · error · MQClientException
The PullConsumer service state not OK, maybe started once, {
Error message
The PullConsumer service state not OK, maybe started once, {serviceState} What it means
Thrown by DefaultMQPullConsumerImpl.start() when the service state is anything other than CREATE_JUST — specifically RUNNING, START_FAILED, or SHUTDOWN_ALREADY. The consumer is a one-shot state machine: start() may only transition CREATE_JUST -> RUNNING; calling start() twice or after shutdown()/a failed start is rejected.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:762
this.offsetStore.load();
boolean registerOK = mQClientFactory.registerConsumer(this.defaultMQPullConsumer.getConsumerGroup(), this);
if (!registerOK) {
this.serviceState = ServiceState.CREATE_JUST;
throw new MQClientException("The consumer group[" + this.defaultMQPullConsumer.getConsumerGroup()
+ "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL),
null);
}
mQClientFactory.start();
log.info("the consumer [{}] start OK", this.defaultMQPullConsumer.getConsumerGroup());
this.serviceState = ServiceState.RUNNING;
break;
case RUNNING:
case START_FAILED:
case SHUTDOWN_ALREADY:
throw new MQClientException("The PullConsumer service state not OK, maybe started once, "
+ this.serviceState
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),
null);
default:
break;
}
}
private void checkConfig() throws MQClientException {
// check consumerGroup
Validators.checkGroup(this.defaultMQPullConsumer.getConsumerGroup());
// consumerGroup
if (null == this.defaultMQPullConsumer.getConsumerGroup()) {
throw new MQClientException(
"consumerGroup is null"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),View on GitHub (pinned to 293f588571)
Solutions
- Create a new DefaultMQPullConsumer instance after shutdown() instead of restarting the same one
- Ensure start() is called exactly once, guarded by your own lifecycle flag or a framework @PostConstruct single invocation
- If a previous start() failed, log the original cause (state will be START_FAILED) and rebuild the consumer with corrected config
Example fix
// before consumer.shutdown(); consumer.start(); // SHUTDOWN_ALREADY -> throws // after consumer.shutdown(); consumer = new DefaultMQPullConsumer(group); consumer.setNamesrvAddr(namesrv); consumer.start();
Defensive patterns
Strategy: validation
Validate before calling
// guard start with your own flag if (started.compareAndSet(false, true)) consumer.start();
Prevention
- Call start() exactly once per instance
- Recreate the consumer after shutdown instead of restarting
- Centralize lifecycle management in one component
When it happens
Trigger: Calling consumer.start() a second time after it already succeeded (state RUNNING); calling start() again after a previous start() threw (state START_FAILED); calling start() after shutdown() (state SHUTDOWN_ALREADY).
Common situations: Reconnect logic that blindly calls start() on every connection loss; lifecycle code where start() is invoked from multiple threads; frameworks re-initializing beans without recreating the consumer object.
Related errors
- The consumer group[{consumerGroup}] has been created before,
- consumerGroup is null
- messageModel is null
- The Factory object[{clientId}] has been created before, and
- The producer service state not OK, maybe started once, {serv
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/b7d108618b059e98.
Report an issue: GitHub.