{"id":"e9dafe81e640a836","repo":"apache/kafka","slug":"networkclient-is-no-longer-active-state-is-state","errorCode":null,"errorMessage":"NetworkClient is no longer active, state is {state}","messagePattern":"NetworkClient is no longer active, state is (.+?)","errorType":"exception","errorClass":"DisconnectException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/NetworkClient.java","lineNumber":795,"sourceCode":"    public void wakeup() {\n        this.selector.wakeup();\n    }\n\n    @Override\n    public void initiateClose() {\n        if (state.compareAndSet(State.ACTIVE, State.CLOSING)) {\n            wakeup();\n        }\n    }\n\n    @Override\n    public boolean active() {\n        return state.get() == State.ACTIVE;\n    }\n\n    private void ensureActive() {\n        if (!active())\n            throw new DisconnectException(\"NetworkClient is no longer active, state is \" + state);\n    }\n\n    /**\n     * Close the network client\n     */\n    @Override\n    public void close() {\n        state.compareAndSet(State.ACTIVE, State.CLOSING);\n        if (state.compareAndSet(State.CLOSING, State.CLOSED)) {\n            cancelBootstrapResolution();\n            ThreadUtils.shutdownExecutorServiceQuietly(bootstrapExecutor, 1, TimeUnit.SECONDS);\n            this.selector.close();\n            this.metadataUpdater.close();\n            if (telemetrySender != null)\n                telemetrySender.close();\n        } else {\n            log.warn(\"Attempting to close NetworkClient that has already been closed.\");\n        }","sourceCodeStart":777,"sourceCodeEnd":813,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/NetworkClient.java#L777-L813","documentation":"Thrown as a DisconnectException by NetworkClient.ensureActive() when an operation is attempted while the NetworkClient state is not ACTIVE (i.e. CLOSING or CLOSED). ensureActive() guards every send/poll path so that work scheduled after initiateClose() or close() fails fast instead of silently dropping requests. The state value in the message indicates how far through shutdown the client has progressed.","triggerScenarios":"Calling client.send(), client.poll(), or any ensureActive-guarded method on a KafkaProducer/KafkaConsumer/AdminClient/KafkaClient after close() or initiateClose() has run. Common in shared-client singletons where one thread closes the client while another issues a request; in @PreDestroy / shutdown hooks racing with in-flight work; and in test teardown that does not wait for outstanding calls to drain.","commonSituations":"Producer/Consumer/Admin closed in a different thread than the caller; bean lifecycle (Spring) destroying the client bean mid-request; reusing a cached client after a broker-driven reconnect failure that triggered close; shutdown hook invoked while the app is still serving traffic.","solutions":["Do not invoke client operations after close(); track lifecycle and gate callers with an AtomicBoolean 'closed' flag.","Ensure close() runs after all in-flight requests complete (drain, await, then close).","Give each long-lived owner its own client instead of sharing one closable instance across independent components.","Catch DisconnectException at the call site and treat it as a terminal signal to stop / rebuild the client."],"exampleFix":"// before\nproducer.send(record);\nproducer.close();   // a concurrent sender thread may now hit ensureActive()\n// after\nproducer.close(Duration.ofSeconds(10)); // close waits for outstanding sends to complete\n// or guard callers:\nif (!closed.get()) producer.send(record);","handlingStrategy":"validation","validationCode":"// Guard every blocking call with an active-state check.\nif (!networkClient.active()) {\n    throw new IllegalStateException(\n        \"NetworkClient is not active (state=\" + networkClient.state() + \"); cannot send or poll.\");\n}\n// Only now proceed to poll/send/awaitReady.","typeGuard":"// Treat 'active' as a precondition predicate, not an assumption.\npublic static boolean isUsable(KafkaClient client) {\n    return client != null && client.active();\n}\n// Usage:\nif (!isUsable(networkClient)) { /* re-create client or fail the operation */ }","tryCatchPattern":"try {\n    networkClient.poll(...);\n} catch (org.apache.kafka.common.errors.DisconnectException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"NetworkClient is no longer active\")) {\n    // client was closed (initiateClose/close ran). Rebuild the client or fail the operation;\n    // retrying on the same instance is NOT safe.\n    }\n    throw e;\n}","preventionTips":["Treat NetworkClient as single-use: once initiateClose()/close() is called the instance is dead.","Ensure only one thread owns the client's lifecycle; concurrent close + use is the usual trigger.","Always check client.active() before blocking helpers from NetworkClientUtils.","Do not swallow DisconnectException without inspecting the message; a stale-connection disconnect is recoverable, a non-active client is not."],"tags":["lifecycle","disconnect","concurrency","shutdown"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}