apache/cassandra · error · InvalidRequestException
Unable to write to denylisted partition
Error message
Unable to write to denylisted partition [0x%s] in %s/%s
What it means
During mutation dispatch (StorageProxy's mutates via StorageProxy/performWrite path), each mutation's partition key is checked against the partition denylist; a denied key causes the write to be rejected with an InvalidRequestException naming the denied partition and its keyspace/table. This is an operator-controlled data quarantine feature.
Solutions
- Remove the partition from the denylist via the denylist mbean/tooling once the issue is resolved.
- Change the application to stop writing to the denied partition key.
- Set denylist_writes_enabled=false in cassandra.yaml if writes should be allowed while reads remain denied.
- Confirm with the cluster operator that the denylist entry is intentional before working around it.
Example fix
// before
session.execute("INSERT INTO flagged (k, v) VALUES (?, ?)", badKey, v); // InvalidRequestException
// after: operator removes key from denylist (nodetool/jmx), then retry the write
session.execute("INSERT INTO flagged (k, v) VALUES (?, ?)", badKey, v); Defensive patterns
Strategy: validation
Validate before calling
// application-side denylist mirror
if (denylistCache.contains(partitionKey)) {
throw new IllegalArgumentException("partition " + partitionKey + " is denylisted; refusing write");
} Try / catch
try {
session.execute(write);
} catch (InvalidRequestException e) {
if (e.getMessage().contains("denylisted partition")) {
// quarantine locally, alert ops, do not retry until entry removed
}
} Prevention
- Sync the denylist state into the app (periodic JMX poll) to pre-filter writes.
- Alert on denylistMetrics.writesRejected.
- Coordinate denylist changes with application owners.
When it happens
Trigger: Any standard (non-CAS) write (INSERT/UPDATE/DELETE/BATCH member) whose partition key is denylisted while partition_denylist_enabled and denylist_writes_enabled are true.
Common situations: Operator denylisted a partition during an incident (corrupt data, runaway writer) while an application keeps writing to it; denylist entries added via JMX persist while clients are unaware.
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
- Unable to CAS write to denylisted partition
- Attempted to read a range containing
- Unable to read denylisted partition
- A storage-attached index cannot be created over multiple…
- A TTL must be greater or equal to 0, but was
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/8da5de09810d6c9c.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/service/StorageProxy.java:1244
ConsistencyLevel consistencyLevel,
boolean mutateAtomically,
Dispatcher.RequestTime requestTime,
PreserveTimestamp preserveTimestamps)
throws WriteTimeoutException, WriteFailureException, UnavailableException, OverloadedException, InvalidRequestException
{
if (DatabaseDescriptor.getPartitionDenylistEnabled() && DatabaseDescriptor.getDenylistWritesEnabled())
{
for (final IMutation mutation : mutations)
{
for (final TableId tid : mutation.getTableIds())
{
if (!partitionDenylist.isKeyPermitted(tid, mutation.key().getKey()))
{
denylistMetrics.incrementWritesRejected();
// While Schema.instance.getTableMetadata() can return a null value, in this case the isKeyPermitted
// call above ensures that we cannot have a null associated tid at this point.
final TableMetadata tmd = Schema.instance.getTableMetadata(tid);
throw new InvalidRequestException(String.format("Unable to write to denylisted partition [0x%s] in %s/%s",
mutation.key().toString(), tmd.keyspace, tmd.name));
}
}
}
}
List<Mutation> augmented = TriggerExecutor.instance.execute(mutations);
String keyspaceName = mutations.iterator().next().getKeyspaceName();
boolean updatesView = Keyspace.open(keyspaceName)
.viewManager
.updatesAffectView(mutations, true);
long size = IMutation.dataSize(augmented != null ? augmented : mutations);
writeMetrics.mutationSize.update(size);
writeMetricsForLevel(consistencyLevel).mutationSize.update(size);
if (augmented != null || mutateAtomically || updatesView)
mutateAtomically(augmented != null ? augmented : (List<Mutation>)mutations, consistencyLevel, updatesView, requestTime);View on GitHub (pinned to 88fd0f6a0e)