apache/cassandra · warning

Seeds list is now empty!

Error message

Seeds list is now empty!

What it means

When an endpoint is removed from gossip via removeEndpoint and it was a seed, Gossiper rebuilds the seeds list and removes the endpoint. If no seeds remain it logs a warning — not an exception — because a cluster with an empty seed list cannot bootstrap new nodes and gossip convergence is at risk.

Solutions

  1. Restore at least one seed: re-add a seed node or fix cassandra.yaml seed_provider list and restart.
  2. Ensure the cluster keeps at least one seed (recommendation: one seed per DC, never zero).
  3. If the node was intentionally removed, update all nodes' seed configs to point at surviving nodes.
  4. If caused by accidental eviction, restart gossip or use nodetool to re-add the endpoint.

Example fix

// before (cassandra.yaml)
seed_provider:
  - seeds: "10.0.0.1"   # only seed, then removed
// after
seed_provider:
  - seeds: "10.0.0.1,10.0.0.2"  # multiple seeds across DCs
Defensive patterns

Strategy: validation

Validate before calling

if (getSeeds().isEmpty()) throw new ConfigurationException("Cluster must retain at least one seed");

Prevention

When it happens

Trigger: removeEndpoint (via unsafeAnnulEndpoint or doStatusCheck eviction) removes the last seed from the configured seed list, leaving seeds empty after buildSeedsList().

Common situations: assassinating/decommissioning every seed node in a small cluster; misconfigured cassandra.yaml where all seeds point at one node that is removed; accidental evictIfExpired of a single-seed dev cluster.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/gms/Gossiper.java:696

    }

    /**
     * Removes the endpoint from Gossip but retains endpoint state
     */
    public void removeEndpoint(InetAddressAndPort endpoint)
    {
        checkProperThreadForStateMutation();
        // do subscribers first so anything in the subscriber that depends on gossiper state won't get confused
        for (IEndpointStateChangeSubscriber subscriber : subscribers)
            subscriber.onRemove(endpoint);

        if(seeds.contains(endpoint))
        {
            buildSeedsList();
            seeds.remove(endpoint);
            logger.info("removed {} from seeds, updated seeds list = {}", endpoint, seeds);
            if (seeds.isEmpty())
                logger.warn("Seeds list is now empty!");
        }

        inflightEcho.remove(endpoint);
        if (disableEndpointRemoval)
            return;

        liveEndpoints.remove(endpoint);
        unreachableEndpoints.remove(endpoint);
        MessagingService.instance().versions.reset(endpoint);
        quarantineEndpoint(endpoint);
        MessagingService.instance().closeOutbound(endpoint);
        MessagingService.instance().removeInbound(endpoint);
        logger.debug("removing endpoint {}", endpoint);
        GossiperDiagnostics.removedEndpoint(this, endpoint);
    }

    @VisibleForTesting
    public void unsafeAnnulEndpoint(InetAddressAndPort endpoint)

View on GitHub (pinned to 88fd0f6a0e)