apache/cassandra · error · FlushException

This output stream is in an unsafe state after an asynchrono

Error message

This output stream is in an unsafe state after an asynchronous flush failed

What it means

When an asynchronous flush fails for any reason other than a connection reset, propagateFailedFlush throws a FlushException stating the output stream is in an unsafe state after a failed flush. This signals that the stream cannot guarantee what was written, so continued use is unsafe and the stream must be abandoned.

Source

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

     */
    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. Treat the stream as failed and abort the streaming session; do not reuse the output stream
  2. Retry the whole transfer on a fresh connection
  3. Check the cause (FlushException.getCause()) to identify the underlying channel failure
  4. Review logs for prior close/error events on the channel that left it in a failed state

Example fix

// before
output.waitUntilFlushed(); // FlushException: unsafe state
// then continuing to write
output.write(...);

// after
try {
    output.waitUntilFlushed();
} catch (FlushException e) {
    output.close();
    throw new IOException("Stream failed, restarting transfer", e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// no pre-call validation exists; rely on failure handling
if (output == null || !output.isOpen()) throw new IOException("Stream not open");

Try / catch

try { output.waitUntilFlushed(); }
catch (FlushException e) {
  logger.error("Stream unsafe after flush failure, cause:", e.getCause());
  output.close();
  restartTransfer();
}

Prevention

When it happens

Trigger: waitUntilFlushed completes and finds a stored flushFailed Throwable that is not classified as a connection reset (e.g. closed channel due to local close, SSL errors, generic IO errors on the socket channel).

Common situations: Socket channel closed locally while a flush was pending; TLS handshake/decryption failures mid-stream; disk or OS-level socket errors during internode streaming.

Related errors


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