apache/rocketmq · error · MQClientException
The producer service state not OK, maybe started once, {serv
Error message
The producer service state not OK, maybe started once, {serviceState} What it means
MQClientException thrown from DefaultMQProducerImpl.start() when the service state is anything other than CREATE_JUST at switch entry - i.e. RUNNING (already started), START_FAILED, or SHUTDOWN_ALREADY. The producer is a one-shot state machine: CREATE_JUST -> RUNNING -> SHUTDOWN_ALREADY, and start() is only legal in the initial state. The message includes the offending state so you can tell which case you hit.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java:281
null);
}
if (startFactory) {
mQClientFactory.start();
}
this.initTopicRoute();
this.mqFaultStrategy.startDetector();
log.info("the producer [{}] start OK. sendMessageWithVIPChannel={}", this.defaultMQProducer.getProducerGroup(),
this.defaultMQProducer.isSendMessageWithVIPChannel());
this.serviceState = ServiceState.RUNNING;
break;
case RUNNING:
case START_FAILED:
case SHUTDOWN_ALREADY:
throw new MQClientException("The producer service state not OK, maybe started once, "
+ this.serviceState
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),
null);
default:
break;
}
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();
RequestFutureHolder.getInstance().startScheduledTask(this);
}
private void checkConfig() throws MQClientException {
Validators.checkGroup(this.defaultMQProducer.getProducerGroup());
if (this.defaultMQProducer.getProducerGroup().equals(MixAll.DEFAULT_PRODUCER_GROUP)) {
throw new MQClientException("producerGroup can not equal " + MixAll.DEFAULT_PRODUCER_GROUP + ", please specify another one.",View on GitHub (pinned to 293f588571)
Solutions
- Audit call sites and guarantee start() runs exactly once per producer instance (guard with a started flag or use Spring lifecycle single-start)
- If the previous start failed, discard the instance and build a fresh DefaultMQProducer (state START_FAILED cannot be recovered)
- If you need to restart after shutdown(), create a new producer object; SHUTDOWN_ALREADY is terminal
- Catch this specific MQClientException in wrappers and treat it as 'already running' (idempotent start) rather than propagating
Example fix
// before
public void ensureStarted() { producer.start(); } // throws on 2nd call
// after
private final AtomicBoolean started = new AtomicBoolean();
public void ensureStarted() throws MQClientException {
if (started.compareAndSet(false, true)) producer.start();
} Defensive patterns
Strategy: validation
Validate before calling
private final AtomicBoolean started = new AtomicBoolean();
public void start() throws MQClientException {
if (started.compareAndSet(false, true)) {
producer.start();
} // else: already started, no-op
} Try / catch
try {
producer.start();
} catch (MQClientException e) {
String state = e.getMessage(); // message embeds RUNNING / SHUTDOWN_ALREADY / START_FAILED
if (state.contains("RUNNING")) { /* idempotent start - ignore */ }
else if (state.contains("SHUTDOWN_ALREADY") || state.contains("START_FAILED")) {
producer = newProducer(); producer.start(); // fresh instance
} else throw e;
} Prevention
- Make start() idempotent in wrapper code with an AtomicBoolean/Lock guard
- Never reuse a producer after shutdown() - build a new instance
- Keep send-retry logic from re-invoking start(); only send() needs retrying
- Centralize producer lifecycle in one component instead of scattering start() calls
When it happens
Trigger: Calling producer.start() twice without shutdown() in between; calling start() on a producer whose previous start() failed midway (state left as START_FAILED); calling start() after shutdown() (state SHUTDOWN_ALREADY is terminal).
Common situations: commonSituations
Related errors
- The PullConsumer service state not OK, maybe started once, {
- The producer group[{producerGroup}] has been created before,
- The producer service state not OK, {serviceState}
- 13
- Sending message to topic[%s] is forbidden.
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/f7f4b5bde3577f53.
Report an issue: GitHub.