apache/cassandra · error · StreamReceiveException

CF was dropped during streaming

Error message

CF %s was dropped during streaming

What it means

During IncomingStreamMessage deserialization, after finding the stream session the receiver resolves the target table by tableId via ColumnFamilyStore.getIfExists. If the column family no longer exists it throws StreamReceiveException with this message: the table was dropped while its data was still being streamed, so the incoming stream has nowhere to land.

Solutions

  1. Wait for in-flight streaming operations to complete before dropping tables, or cancel/let the stream session fail and re-run streaming afterwards
  2. If the drop was intentional, the failure is benign: verify the failed session is closed and no retries keep streaming to the dropped table
  3. If the drop was unintentional, restore the table schema (recreate table / restore schema from backup) and re-run repair or the streaming operation
  4. Check schema agreement between nodes (nodetool describecluster) to rule out schema disagreement causing one node to see the table as dropped

Example fix

// before
DROP TABLE ks.t;            // while bootstrap streaming t is in flight
// after
nodetool netstats           // confirm streaming finished first
DROP TABLE ks.t;
Defensive patterns

Strategy: try-catch

Validate before calling

ColumnFamilyStore cfs = ColumnFamilyStore.getIfExists(header.tableId);
if (cfs == null) { logger.warn("table {} dropped during streaming; aborting receive", header.tableId); abortSession(session); return; }

Try / catch

try { receiveStream(header, input); }
catch (StreamReceiveException e) {
    logger.warn("stream aborted: {}", e.getMessage()); // benign if drop was intentional
}

Prevention

When it happens

Trigger: A schema change (DROP TABLE / DROP KEYSPACE) executed on the receiving node while a peer is actively streaming sstables for that tableId; the stream session exists but its target CF was removed concurrently.

Common situations: Running DROP TABLE or schema migrations concurrently with repair/bootstrap streaming; a node joining while a developer drops unused tables; cqlsh-driven schema cleanup racing an ongoing decommission/rebuild stream.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/streaming/messages/IncomingStreamMessage.java:44

import org.apache.cassandra.streaming.StreamManager;
import org.apache.cassandra.streaming.StreamReceiveException;
import org.apache.cassandra.streaming.StreamSession;
import org.apache.cassandra.streaming.StreamingChannel;
import org.apache.cassandra.streaming.StreamingDataOutputPlus;

public class IncomingStreamMessage extends StreamMessage
{
    public static Serializer<IncomingStreamMessage> serializer = new Serializer<IncomingStreamMessage>()
    {
        public IncomingStreamMessage deserialize(DataInputPlus input, int version) throws IOException
        {
            StreamMessageHeader header = StreamMessageHeader.serializer.deserialize(input, version);
            StreamSession session = StreamManager.instance.findSession(header.sender, header.planId, header.sessionIndex, header.sendByFollower);
            if (session == null)
                throw new IllegalStateException(String.format("unknown stream session: %s - %d", header.planId, header.sessionIndex));
            ColumnFamilyStore cfs = ColumnFamilyStore.getIfExists(header.tableId);
            if (cfs == null)
                throw new StreamReceiveException(session, "CF " + header.tableId + " was dropped during streaming");

            try
            {
                IncomingStream incomingData = cfs.getStreamManager().prepareIncomingStream(session, header);
                incomingData.read(input, version);

                return new IncomingStreamMessage(incomingData, header);
            }
            catch (Throwable t)
            {
                if (t instanceof StreamReceiveException)
                    throw (StreamReceiveException) t;
                // make sure to wrap so the caller always has access to the session to call onError
                throw new StreamReceiveException(session, t);
            }
        }

        public void serialize(IncomingStreamMessage message, StreamingDataOutputPlus out, int version, StreamSession session)

View on GitHub (pinned to 88fd0f6a0e)