apache/rocketmq · error · MQClientException
The PullConsumer service state not OK, maybe started once,
Error message
The PullConsumer service state not OK, maybe started once,
What it means
MQClientException thrown by DefaultLitePullConsumerImpl.start() when the service state is RUNNING (already started), START_FAILED, or SHUTDOWN_ALREADY — i.e. start() was called on an instance that cannot transition from CREATE_JUST again. The message appends the current state and a FAQ URL for client service state issues.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java:321
startScheduleTask();
this.serviceState = ServiceState.RUNNING;
log.info("the consumer [{}] start OK", this.defaultLitePullConsumer.getConsumerGroup());
try {
operateAfterRunning();
} catch (Exception e) {
shutdown();
throw e;
}
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 initScheduledThreadPoolExecutor() {
this.scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(
this.defaultLitePullConsumer.getPullThreadNums(),
new ThreadFactoryImpl("PullMsgThread-" + this.defaultLitePullConsumer.getConsumerGroup())
);
}
private void initMQClientFactory() throws MQClientException {
this.mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(this.defaultLitePullConsumer, this.rpcHook);
boolean registerOK = mQClientFactory.registerConsumer(this.defaultLitePullConsumer.getConsumerGroup(), this);View on GitHub (pinned to 293f588571)
Solutions
- Call start() exactly once per instance, guarded by your own started flag or framework singleton lifecycle
- To restart, build a new DefaultLitePullConsumer — instances are not reusable after shutdown
- If the first start() threw, do not retry start() on the same object; fix the root cause and recreate
- Audit Spring configs for duplicate init methods on the same consumer bean
Example fix
// before: reconnect loop reuses instance
if (broken) { consumer.shutdown(); consumer.start(); } // state not OK
// after: recreate the instance
if (broken) {
consumer.shutdown();
consumer = buildConsumer(); // new DefaultLitePullConsumer with same config
consumer.start();
} Defensive patterns
Strategy: validation
Validate before calling
// wrap start with an idempotent guard
private final AtomicBoolean started = new AtomicBoolean(false);
public synchronized void ensureStarted() {
if (started.compareAndSet(false, true)) {
consumer.start();
}
} Try / catch
try {
consumer.start();
} catch (MQClientException e) {
if (e.getMessage() != null && e.getMessage().contains("service state not OK")) {
// duplicate start: safe to ignore only if already RUNNING; otherwise recreate instance
} else throw e;
} Prevention
- Call start() once from a single lifecycle owner
- Recreate instances instead of restarting them
- Check Spring bean init-method duplication when this appears at boot
When it happens
Trigger: Calling consumer.start() twice; calling start() again after a failed start (state START_FAILED); calling start() on an instance previously shut down (SHUTDOWN_ALREADY). Restart logic in health checks or reconnect loops commonly triggers it.
Common situations: Framework lifecycle hooks (Spring @PostConstruct plus a manual init) both calling start(); retry wrappers that call start() after shutdown to 'reconnect' a pull consumer; ignoring a first start() exception and retrying start() on the poisoned instance.
Related errors
- The consumer not running, please start it first.
- Subscribe and assign are mutually exclusive.
- consumerGroup can not equal
- messageModel is null
- allocateMessageQueueStrategy is null
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/e2e4a687af9f71cd.
Report an issue: GitHub.