apache/cassandra · error · InvalidRequestException

Unable to read denylisted partition

Error message

Unable to read denylisted partition [0x%s] in %s/%s

What it means

InvalidRequestException thrown before executing a single-partition read when the partition key is on the partition denylist. The denylist feature (partition_denylist) blocks reads of specific partitions, counting the rejection in denylistMetrics.readsRejected.

Solutions

  1. Confirm the key is denylisted: `nodetool isdenylisted <keyspace> <table> <partitionKey>`.
  2. Remove the entry if the read is legitimate: `nodetool allowlist` / remove via denylist JMX operation, or update partition_denylist configuration.
  3. Change application queries to stop touching the denylisted partition key.
  4. If denylisting was accidental, fix cassandra.yaml (partition_denylist_entries / denylist files) and reload.

Example fix

// before
ResultSet rs = session.execute("SELECT * FROM ks.tbl WHERE pk = ?", denylistedKey);
// after
if (!denylistService.isKeyDenied(denylistedKey)) {
    ResultSet rs = session.execute("SELECT * FROM ks.tbl WHERE pk = ?", denylistedKey);
} else { /* use remediated key or fail fast */ }
Defensive patterns

Strategy: validation

Validate before calling

boolean denied = (boolean) jmxConn.invoke(denylistMbean, "isPartitionDenylisted",
        new Object[]{keyspace, table, partitionKeyHex}, new String[]{"java.lang.String","java.lang.String","java.lang.String"});
if (denied) skipRead(partitionKeyHex);

Try / catch

catch (InvalidRequestException e) {
    if (e.getMessage().contains("denylisted partition")) {
        metrics.denylistedReadRejected();
        return null; // or route to remediation path
    }
    throw e;
}

Prevention

When it happens

Trigger: Any SinglePartitionReadCommand (SELECT by full primary key, or LWT read) issued against a table/key that an operator added via nodetool denylist or the denylist JMX/API.

Common situations: Application still reading a key that security/incident-response put on the denylist after data corruption or a bad-data incident; denylist left enabled after remediation; tests run against tables that have denylisted entries from earlier experiments.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/StorageProxy.java:2184

    {
        return PartitionIterators.getOnlyElement(read(SinglePartitionReadCommand.Group.one(command), consistencyLevel, requestTime), command);
    }

    /**
     * Performs the actual reading of a row out of the StorageService, fetching
     * a specific set of column names from a given column family.
     */
    public static PartitionIterator read(SinglePartitionReadCommand.Group group, ConsistencyLevel consistencyLevel, Dispatcher.RequestTime requestTime)
    throws UnavailableException, IsBootstrappingException, ReadFailureException, ReadTimeoutException, InvalidRequestException
    {
        if (DatabaseDescriptor.getPartitionDenylistEnabled() && DatabaseDescriptor.getDenylistReadsEnabled())
        {
            for (SinglePartitionReadCommand command : group.queries)
            {
                if (!partitionDenylist.isKeyPermitted(command.metadata().id, command.partitionKey().getKey()))
                {
                    denylistMetrics.incrementReadsRejected();
                    throw new InvalidRequestException(String.format("Unable to read denylisted partition [0x%s] in %s/%s",
                                                                    command.partitionKey().toString(), command.metadata().keyspace, command.metadata().name));
                }
            }
        }

        return consistencyLevel.isSerialConsistency()
             ? readWithConsensus(group, consistencyLevel, requestTime)
             : dispatchReadWithRetryOnDifferentSystem(group, consistencyLevel, ReadCoordinator.DEFAULT, requestTime);
    }

    public static boolean hasJoined()
    {
        ClusterMetadata metadata = ClusterMetadata.current();
        if (metadata == null)
            return false;

        if (metadata.myNodeId() == NodeId.UNREGISTERED)
            return false;

View on GitHub (pinned to 88fd0f6a0e)