apache/cassandra · error · IllegalStateException

Can't upgrade the first node when STATUS =

Error message

Can't upgrade the first node when STATUS = 

What it means

GossipHelper.toNodeState maps legacy gossip STATUS application-state values to TCM NodeState values; a STATUS value not in the handled set throws IllegalStateException because the first-node upgrade path cannot classify that endpoint. This is a strictness guard during the gossip-to-TCM migration of the seed/first node.

Source

Thrown at src/java/org/apache/cassandra/tcm/compatibility/GossipHelper.java:244

        {
            throw new RuntimeException(e);
        }
    }

    private static NodeState toNodeState(InetAddressAndPort endpoint, EndpointState epState)
    {
        assert epState != null;

        String status = epState.getStatus();
        if (status.equals(VersionedValue.STATUS_NORMAL) ||
            status.equals(VersionedValue.SHUTDOWN) ||
            status.equals(VersionedValue.HIBERNATE))
            return NodeState.JOINED;
        if (status.equals(VersionedValue.STATUS_LEFT))
            return NodeState.LEFT;
        if (status.isEmpty())
            return NodeState.REGISTERED;
        throw new IllegalStateException("Can't upgrade the first node when STATUS = " + status + " for node " + endpoint);
    }

    public static NodeAddresses getAddressesFromEndpointState(InetAddressAndPort endpoint, EndpointState epState)
    {
        if (endpoint.equals(getBroadcastAddressAndPort()))
            return NodeAddresses.current();
        try
        {
            InetAddressAndPort local = getEitherState(endpoint, epState, INTERNAL_ADDRESS_AND_PORT, INTERNAL_IP, DatabaseDescriptor.getStoragePort());
            InetAddressAndPort nativeAddress = getEitherState(endpoint, epState, NATIVE_ADDRESS_AND_PORT, RPC_ADDRESS, DatabaseDescriptor.getNativeTransportPort());
            return new NodeAddresses(UUID.randomUUID(), endpoint, local, nativeAddress);
        }
        catch (UnknownHostException e)
        {
            throw new ConfigurationException("Unknown host in epState for " + endpoint + " : " + epState, e);
        }
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Ensure the whole cluster is quiesced (no bootstrap/leaving/move in flight) before the TCM upgrade of the first node
  2. Remove dead/stale endpoints from gossip (nodetool removenode / assassinate where appropriate) before upgrading
  3. Upgrade all nodes to the gossip-compat version before starting the migration
  4. If a legit status is unhandled, extend toNodeState with the missing mapping

Example fix

// before
if (status.isEmpty())
    return NodeState.REGISTERED;
throw new IllegalStateException("Can't upgrade the first node when STATUS = " + status);
// after
if (status.isEmpty())
    return NodeState.REGISTERED;
if (status.startsWith(VersionedValue.STATUS_BOOTSTRAPPING))
    return NodeState.BOOTSTRAPPING;
throw new IllegalStateException("Can't upgrade the first node when STATUS = " + status);
Defensive patterns

Strategy: validation

Validate before calling

String status = getGossipStatus(endpoint);
Set<String> ok = Set.of(STATUS_NORMAL, STATUS_BOOTSTRAPPING, STATUS_LEAVING, STATUS_LEFT, HIBERNATE, "");
if (!ok.contains(status) && !status.startsWith("BOOTSTRAP"))
    log.warn("Unmapped gossip status {} for {} before upgrade", status, endpoint);

Try / catch

try { NodeState ns = GossipHelper.toNodeState(endpoint, epState, tokens); }
catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Can't upgrade the first node")) { /* quiesce cluster, clean gossip, retry */ }
    else throw e;
}

Prevention

When it happens

Trigger: Upgrading the first node when some endpoint's gossip status is an unrecognized string (empty handled, JOINED/LEFT/HIBERNATE handled, anything else throws), e.g. BOOTSTRAPPING variants or unexpected/legacy values.

Common situations: Mixed-version gossip during rolling upgrade; stale gossip state from long-dead nodes; nodes mid-operation (e.g. leaving/moving) at upgrade time; corrupted endpoint state.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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