{"record":{"id":"710dc65c3a9f79ca","repo":"apache/cassandra","slug":"this-output-stream-is-in-an-unsafe-state-after-an","errorCode":null,"errorMessage":"This output stream is in an unsafe state after an asynchronous flush failed","messagePattern":"This output stream is in an unsafe state after an asynchronous flush failed","errorType":"exception","errorClass":"FlushException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/net/AsyncChannelOutputPlus.java","lineNumber":202,"sourceCode":"     */\n    protected void releaseSpace(long bytesFlushed)\n    {\n        long newFlushed = flushed + bytesFlushed;\n        flushed = newFlushed;\n\n        Thread thread = waiting;\n        if (thread != null && signalWhenFlushed <= newFlushed)\n            LockSupport.unpark(thread);\n    }\n\n    private void propagateFailedFlush() throws IOException\n    {\n        Throwable t = flushFailed;\n        if (t != null)\n        {\n            if (SocketFactory.isCausedByConnectionReset(t))\n                throw new FlushException(\"The channel this output stream was writing to has been closed\", t);\n            throw new FlushException(\"This output stream is in an unsafe state after an asynchronous flush failed\", t);\n        }\n    }\n\n    @Override\n    abstract protected void doFlush(int count) throws IOException;\n\n    abstract public long position();\n\n    public long flushed()\n    {\n        // external flushed (that which has had flush() invoked implicitly or otherwise) == internal flushing\n        return flushing;\n    }\n\n    public long flushedToNetwork()\n    {\n        return flushedToNetwork;\n    }","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/net/AsyncChannelOutputPlus.java#L184-L220","documentation":"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.","triggerScenarios":"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).","commonSituations":"Socket channel closed locally while a flush was pending; TLS handshake/decryption failures mid-stream; disk or OS-level socket errors during internode streaming.","solutions":["Treat the stream as failed and abort the streaming session; do not reuse the output stream","Retry the whole transfer on a fresh connection","Check the cause (FlushException.getCause()) to identify the underlying channel failure","Review logs for prior close/error events on the channel that left it in a failed state"],"exampleFix":"// before\noutput.waitUntilFlushed(); // FlushException: unsafe state\n// then continuing to write\noutput.write(...);\n\n// after\ntry {\n    output.waitUntilFlushed();\n} catch (FlushException e) {\n    output.close();\n    throw new IOException(\"Stream failed, restarting transfer\", e);\n}\n","handlingStrategy":"try-catch","validationCode":"// no pre-call validation exists; rely on failure handling\nif (output == null || !output.isOpen()) throw new IOException(\"Stream not open\");","typeGuard":null,"tryCatchPattern":"try { output.waitUntilFlushed(); }\ncatch (FlushException e) {\n  logger.error(\"Stream unsafe after flush failure, cause:\", e.getCause());\n  output.close();\n  restartTransfer();\n}","preventionTips":["Never reuse an AsyncChannelOutputPlus after a failed flush","Inspect getCause() to distinguish local closes from network errors","Keep transfer sizes modest so failed transfers are cheap to retry"],"tags":["network","streaming","io"],"backgroundTag":"stream-flush-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}