{"record":{"id":"b2af6e6c4acd4fac","repo":"apache/cassandra","slug":"unable-to-cas-write-to-denylisted-partition-0x-s","errorCode":null,"errorMessage":"Unable to CAS write to denylisted partition [0x%s] in %s/%s","messagePattern":"Unable to CAS write to denylisted partition \\[0x(.+?)\\] in (.+?)/(.+?)","errorType":"exception","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/StorageProxy.java","lineNumber":381,"sourceCode":"     *\n     * @return null if the operation succeeds in updating the row, or the current values corresponding to conditions.\n     * (since, if the CAS doesn't succeed, it means the current value do not match the conditions).\n     */\n    public static RowIterator cas(String keyspaceName,\n                                  String cfName,\n                                  DecoratedKey key,\n                                  CASRequest request,\n                                  ConsistencyLevel consistencyForPaxos,\n                                  ConsistencyLevel consistencyForCommit,\n                                  ClientState clientState,\n                                  long nowInSeconds,\n                                  Dispatcher.RequestTime requestTime)\n    throws UnavailableException, IsBootstrappingException, RequestFailureException, RequestTimeoutException, InvalidRequestException, CasWriteUnknownResultException\n    {\n        if (DatabaseDescriptor.getPartitionDenylistEnabled() && DatabaseDescriptor.getDenylistWritesEnabled() && !partitionDenylist.isKeyPermitted(keyspaceName, cfName, key.getKey()))\n        {\n            denylistMetrics.incrementWritesRejected();\n            throw new InvalidRequestException(String.format(\"Unable to CAS write to denylisted partition [0x%s] in %s/%s\",\n                                                            key, keyspaceName, cfName));\n        }\n\n        ConsensusAttemptResult lastAttemptResult = null;\n        do\n        {\n            ClusterMetadata cm = ClusterMetadata.current();\n            TableMetadata metadata = Schema.instance.validateTable(keyspaceName, cfName);\n            ConsensusRoutingDecision decision = consensusRouting(cm, metadata, key, consistencyForPaxos, requestTime, true);\n            switch (decision.target)\n            {\n                case paxosV2:\n                    lastAttemptResult = Paxos.cas(key,\n                                                  request,\n                                                  consistencyForPaxos,\n                                                  consistencyForCommit,\n                                                  clientState,\n                                                  requestTime,","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/StorageProxy.java#L363-L399","documentation":"StorageProxy.cas rejects compare-and-set (LWT) writes whose partition key is on the partition denylist. When partition denylisting and denylisted-write rejection are enabled, isKeyPermitted() failing causes an InvalidRequestException so the denied write never enters the Paxos protocol.","triggerScenarios":"Executing an INSERT ... IF NOT EXISTS / UPDATE ... IF / DELETE ... IF (CAS/LWT) on a partition that was added to the partition denylist while DatabaseDescriptor.getPartitionDenylistEnabled() and getDenylistWritesEnabled() are true.","commonSituations":"Operators denylisting a problematic partition (e.g. during incident mitigation or bad-data quarantine) while an application keeps issuing conditional writes to it; keyspace/table names in the denylist entry matching the CAS target.","solutions":["Remove the partition from the denylist (via the denylist JMX/mbean or the operational tooling) so the key is permitted again.","Stop issuing LWT/CAS writes to the denied partition, or redirect the application to a different key.","If denylisting writes is too aggressive, set cassandra.denylist_writes_enabled=false (or the equivalent yaml option) while keeping denylisting for reads only."],"exampleFix":"// before: CAS write to denied partition\nUPDATE users USING TTL 60 SET v=? WHERE k=? IF EXISTS;\n// after: remove key from denylist first (nodetool/jmx denylist removal), or use non-LWT write\nUPDATE users USING TTL 60 SET v=? WHERE k=?;","handlingStrategy":"validation","validationCode":"// check denylist state before issuing a CAS (via operator tooling/jmx)\nboolean denied = denylistMbean.isKeyPermitted(keyspace, table, key); // if exposed\nif (!denied) throw new IllegalStateException(\"key is denylisted; skip CAS write\");","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(casQuery);\n} catch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"denylisted partition\")) {\n        // alert ops / route write elsewhere; do not blind-retry\n    }\n}","preventionTips":["Keep an application-side copy of denylisted keys and skip them proactively.","Subscribe to ops notifications when denylist entries change.","Monitor denylistMetrics.writesRejected for unexpected spikes."],"tags":["lightweight-transactions","denylist","invalid-request","storage-proxy"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}