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

  1. Audit call sites and guarantee start() runs exactly once per producer instance (guard with a started flag or use Spring lifecycle single-start)
  2. If the previous start failed, discard the instance and build a fresh DefaultMQProducer (state START_FAILED cannot be recovered)
  3. If you need to restart after shutdown(), create a new producer object; SHUTDOWN_ALREADY is terminal
  4. 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

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


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