{"record":{"id":"e2e4a687af9f71cd","repo":"apache/rocketmq","slug":"the-pullconsumer-service-state-not-ok-maybe-start","errorCode":null,"errorMessage":"The PullConsumer service state not OK, maybe started once, ","messagePattern":"The PullConsumer service state not OK, maybe started once, ","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":321,"sourceCode":"\n                startScheduleTask();\n\n                this.serviceState = ServiceState.RUNNING;\n\n                log.info(\"the consumer [{}] start OK\", this.defaultLitePullConsumer.getConsumerGroup());\n\n                try {\n                    operateAfterRunning();\n                } catch (Exception e) {\n                    shutdown();\n                    throw e;\n                }\n\n                break;\n            case RUNNING:\n            case START_FAILED:\n            case SHUTDOWN_ALREADY:\n                throw new MQClientException(\"The PullConsumer service state not OK, maybe started once, \"\n                    + this.serviceState\n                    + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),\n                    null);\n            default:\n                break;\n        }\n    }\n\n    private void initScheduledThreadPoolExecutor() {\n        this.scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(\n                this.defaultLitePullConsumer.getPullThreadNums(),\n                new ThreadFactoryImpl(\"PullMsgThread-\" + this.defaultLitePullConsumer.getConsumerGroup())\n        );\n    }\n\n    private void initMQClientFactory() throws MQClientException {\n        this.mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(this.defaultLitePullConsumer, this.rpcHook);\n        boolean registerOK = mQClientFactory.registerConsumer(this.defaultLitePullConsumer.getConsumerGroup(), this);","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L303-L339","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: reconnect loop reuses instance\nif (broken) { consumer.shutdown(); consumer.start(); } // state not OK\n\n// after: recreate the instance\nif (broken) {\n    consumer.shutdown();\n    consumer = buildConsumer(); // new DefaultLitePullConsumer with same config\n    consumer.start();\n}","handlingStrategy":"validation","validationCode":"// wrap start with an idempotent guard\nprivate final AtomicBoolean started = new AtomicBoolean(false);\npublic synchronized void ensureStarted() {\n    if (started.compareAndSet(false, true)) {\n        consumer.start();\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    consumer.start();\n} catch (MQClientException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"service state not OK\")) {\n        // duplicate start: safe to ignore only if already RUNNING; otherwise recreate instance\n    } else throw e;\n}","preventionTips":["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"],"tags":["rocketmq","lifecycle","consumer","lite-pull","state"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}