apache/kafka · error · DisconnectException
NetworkClient is no longer active, state is {state}
Error message
NetworkClient is no longer active, state is {state} What it means
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.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/NetworkClient.java:795
public void wakeup() {
this.selector.wakeup();
}
@Override
public void initiateClose() {
if (state.compareAndSet(State.ACTIVE, State.CLOSING)) {
wakeup();
}
}
@Override
public boolean active() {
return state.get() == State.ACTIVE;
}
private void ensureActive() {
if (!active())
throw new DisconnectException("NetworkClient is no longer active, state is " + state);
}
/**
* Close the network client
*/
@Override
public void close() {
state.compareAndSet(State.ACTIVE, State.CLOSING);
if (state.compareAndSet(State.CLOSING, State.CLOSED)) {
cancelBootstrapResolution();
ThreadUtils.shutdownExecutorServiceQuietly(bootstrapExecutor, 1, TimeUnit.SECONDS);
this.selector.close();
this.metadataUpdater.close();
if (telemetrySender != null)
telemetrySender.close();
} else {
log.warn("Attempting to close NetworkClient that has already been closed.");
}View on GitHub (pinned to c31c9215e1)
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.
Example fix
// before producer.send(record); producer.close(); // a concurrent sender thread may now hit ensureActive() // after producer.close(Duration.ofSeconds(10)); // close waits for outstanding sends to complete // or guard callers: if (!closed.get()) producer.send(record);
Defensive patterns
Strategy: validation
Validate before calling
// Guard every blocking call with an active-state check.
if (!networkClient.active()) {
throw new IllegalStateException(
"NetworkClient is not active (state=" + networkClient.state() + "); cannot send or poll.");
}
// Only now proceed to poll/send/awaitReady. Type guard
// Treat 'active' as a precondition predicate, not an assumption.
public static boolean isUsable(KafkaClient client) {
return client != null && client.active();
}
// Usage:
if (!isUsable(networkClient)) { /* re-create client or fail the operation */ } Try / catch
try {
networkClient.poll(...);
} catch (org.apache.kafka.common.errors.DisconnectException e) {
if (e.getMessage() != null && e.getMessage().startsWith("NetworkClient is no longer active")) {
// client was closed (initiateClose/close ran). Rebuild the client or fail the operation;
// retrying on the same instance is NOT safe.
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Client was shutdown before response was read
- Producer closed while allocating memory
- Producer closed while send in progress
- This consumer has already been closed.
- Requested metadata update after close
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/e9dafe81e640a836.json.
Report an issue: GitHub.