apache/cassandra · error · InvalidRequestException

Attempted to serve data request from node in

Error message

Attempted to serve %s data request from %s node in %s

What it means

ReadCommandVerbHandler.checkTokenOwnership rejects a data request when the only local replica for the requested token is a transient replica but the read command requires full data (does not accept transient reads). Serving full reads from a transient replica would violate read consistency, so the message is dropped as invalid request.

Solutions

  1. Fix replication so every range has enough full replicas (complete pending bootstrap/decommission, run repair)
  2. Retry the read via a coordinator that routes to a full replica
  3. Verify the coordinator's token map is current (restart or wait for gossip/metadata convergence)
  4. If transient replication is not intended, ensure the read/command consistency and options do not rely on transient ranges
Defensive patterns

Strategy: validation

Validate before calling

// before relying on reads on a node
NodeToolOutput status = nodetool("info");
if (clusterHasPendingOrLeavingNodes(status)) {
    // ranges may be served by transient replicas; finish topology ops first
    throw new PreconditionFailed("complete bootstrap/decommission before reads");
}

Prevention

When it happens

Trigger: A coordinator routes a full (non-transient) read for a token to a node that only holds that range as a transient replica (e.g., RF lacks a full replica due to pending/decommissioning nodes), and doVerb -> checkTokenOwnership detects localReplica.isTransient().

Common situations: Cluster running with transient replication enabled while a node is still being bootstrapped or decommissioned; coordinator ring cache stale after topology change; misconfigured rack/DC leaving a range covered only by transient replicas.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/db/ReadCommandVerbHandler.java:203

        {
            Token token = ((SinglePartitionReadCommand)command).partitionKey().getToken();
            Replica localReplica = getLocalReplica(metadata, token, command.metadata().keyspace);
            if (localReplica == null)
            {
                metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
                localReplica = getLocalReplica(metadata, token, command.metadata().keyspace);
            }
            if (localReplica == null)
            {
                StorageService.instance.incOutOfRangeOperationCount();
                Keyspace.open(command.metadata().keyspace).metric.outOfRangeTokenReads.inc();
                throw InvalidRoutingException.forTokenRead(message.from(), token, metadata.epoch, message.payload);
            }

            if (!command.acceptsTransient() && localReplica.isTransient())
            {
                MessagingService.instance().metrics.recordDroppedMessage(message, message.elapsedSinceCreated(NANOSECONDS), NANOSECONDS);
                throw new InvalidRequestException(String.format("Attempted to serve %s data request from %s node in %s",
                                                                command.acceptsTransient() ? "transient" : "full",
                                                                localReplica.isTransient() ? "transient" : "full",
                                                                this));
            }
        }
        else
        {
            AbstractBounds<PartitionPosition> range = ((PartitionRangeReadCommand) command).dataRange().keyRange();

            // TODO: preexisting issue: for the range queries or queries that span multiple replicas, we can only make requests where the right token is owned, but not the left one
            Replica maxTokenLocalReplica = getLocalReplica(metadata, range.right.getToken(), command.metadata().keyspace);
            if (maxTokenLocalReplica == null)
            {
                metadata = ClusterMetadataService.instance().fetchLogFromPeerOrCMS(metadata, message.from(), message.epoch());
                maxTokenLocalReplica = getLocalReplica(metadata, range.right.getToken(), command.metadata().keyspace);
            }
            if (maxTokenLocalReplica == null)
            {

View on GitHub (pinned to 88fd0f6a0e)