apache/cassandra · error · FlushException

The channel this output stream was writing to has been close

Error message

The channel this output stream was writing to has been closed

What it means

AsyncChannelOutputPlus waits for asynchronous channel flushes to complete; propagateFailedFlush converts a stored flush failure into a FlushException. When the underlying failure is a connection reset (SocketFactory.isCausedByConnectionReset), the message indicates the channel the stream was writing to has been closed — i.e. the remote peer is gone.

Source

Thrown at src/java/org/apache/cassandra/net/AsyncChannelOutputPlus.java:201

     * This may only be invoked by the eventLoop, never by the writer thread.
     */
    protected void releaseSpace(long bytesFlushed)
    {
        long newFlushed = flushed + bytesFlushed;
        flushed = newFlushed;

        Thread thread = waiting;
        if (thread != null && signalWhenFlushed <= newFlushed)
            LockSupport.unpark(thread);
    }

    private void propagateFailedFlush() throws IOException
    {
        Throwable t = flushFailed;
        if (t != null)
        {
            if (SocketFactory.isCausedByConnectionReset(t))
                throw new FlushException("The channel this output stream was writing to has been closed", t);
            throw new FlushException("This output stream is in an unsafe state after an asynchronous flush failed", t);
        }
    }

    @Override
    abstract protected void doFlush(int count) throws IOException;

    abstract public long position();

    public long flushed()
    {
        // external flushed (that which has had flush() invoked implicitly or otherwise) == internal flushing
        return flushing;
    }

    public long flushedToNetwork()
    {
        return flushedToNetwork;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Retry the streaming operation once the peer is back and the connection is re-established
  2. Inspect logs on the remote node to determine why it closed/reset the connection
  3. Check network stability (firewalls, load balancer idle timeouts) between nodes
  4. Ensure the application handles FlushException by aborting the in-flight stream cleanly

Example fix

// before
output.writeFileToChannel(...); // throws FlushException on reset

// after
try {
    output.writeFileToChannel(...);
} catch (FlushException e) {
    logger.warn("Peer connection lost during stream, scheduling retry", e);
    scheduleStreamRetry(plan);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// proactively check channel state
if (!channel.isOpen()) throw new IOException("Channel already closed before streaming");

Try / catch

try { output.writeFileToChannel(file, length, limits); }
catch (FlushException e) {
  if (e.getMessage().contains("closed")) { scheduleStreamRetry(plan); }
  else throw e;
}

Prevention

When it happens

Trigger: A flush issued asynchronously to the socket channel fails because the connection was reset by the peer (TCP RST) or the channel was closed; waitUntilFlushed then surfaces this via propagateFailedFlush.

Common situations: Remote node crashed or restarted mid-stream; network interruption/severed TCP connection during streaming; peer closed the socket while this node was still writing data.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ec2f3f7af7e85359. Report an issue: GitHub.