Let's say you restart a Cassandra node for a patch or config change. The node comes up, you run nodetool status, and it shows the node as UN (Up Normal) but it never shows up in the ring. Or worse, it shows DN (Down Normal) and stays there. Other nodes ignore it. You check logs and see messages like Gossip stage has 0 active tasks or Unable to gossip with any seeds. This is the classic gossip protocol failure after a restart.
I've seen this happen on Cassandra 3.11 and 4.0 clusters, especially when you restart a node that's been down for a while or when you change the seed list without restarting all nodes. The root cause is simple: the gossip state on that node is stale or mismatched with the rest of the cluster. Cassandra uses gossip to share node status and schema versions. If the node's local gossip info doesn't match what other nodes have in system.peers, it can't sync.
Here's the fix. It's safe — you won't lose data. But you'll need to be careful about the order of steps.
Step-by-step fix
- Stop the stuck node — run
nodetool stopdaemonor kill the process. Wait until it's fully down (check withps aux | grep cassandra). - Clear the gossip state — go to the data directory (usually
/var/lib/cassandra/data/or/opt/cassandra/data/). Delete thesystem/peersandsystem/peer_eventsfolders. Example:
Don't delete anything else — you still need the keyspace data, commitlog, andrm -rf /var/lib/cassandra/data/system/peers*
rm -rf /var/lib/cassandra/data/system/peer_events*system.local. - Restart the node — start Cassandra again. It will rebuild the gossip state from the seed nodes. Run
nodetool statusafter a minute. The node should now show as UN and appear in the ring. - Run a repair — once the node is up, run
nodetool repairon the node. This ensures data consistency. On a large cluster, I'd run it with-pr(primary range) to reduce load:nodetool repair -pr
Why this works
When you delete the peers data, the node forgets all gossip history. On restart, it contacts the seed nodes (from cassandra.yaml) and gets a fresh view of the cluster. The seeds share the current state, and the node syncs its local info. I've used this on a 10-node cluster where one node wouldn't rejoin after a 2-hour downtime. Took 5 minutes.
What to check if it still fails
If the node still won't join after clearing peers:
- Check seed list — make sure this node's
cassandra.yamllists at least one seed that is currently UN. If all seeds are down, gossip can't initialize. You can temporarily set the seed to another alive node (even itself if it's the only one). - Firewall — verify port 7000 (or 8609 in Cassandra 4.0) is open between nodes. Run
telnet <seed_ip> 7000from the stuck node. - Check logs — look in
/var/log/cassandra/system.logforUnable to gossip with any seedsorNo gossip backlog. That points to network or seed issues. - Try a full restart of all nodes — as a last resort, if you're in a dev environment, restart the entire cluster. But in production, the fix above should work 99% of the time.
One more thing: if you changed the seed list, you must restart all nodes that are not seeds first, then the seeds. This is a common mistake I've tripped over myself.
You got this. The gossip protocol is flaky, but the fix is straightforward.