apache/cassandra · warning

Got denylist mutation for unknown ks/cf: {}/{}. Skipping ref

Error message

Got denylist mutation for unknown ks/cf: {}/{}. Skipping refresh.

What it means

PartitionDenylist.refreshTableDenylist logs this warning when a denylist mutation (add/remove key) targets a keyspace/table that cannot be resolved to a TableId. The refresh is skipped and the method returns false; the denylist cache is left unchanged.

Source

Thrown at src/java/org/apache/cassandra/schema/PartitionDenylist.java:530

            }
            return results;
        }
        catch (final RequestExecutionException e)
        {
            logger.error("Error reading full partition denylist from "
                         + SchemaConstants.DISTRIBUTED_KEYSPACE_NAME + "." + SystemDistributedKeyspace.PARTITION_DENYLIST_TABLE +
                         ". Partition Denylisting will be compromised. Exception: " + e);
            return Collections.emptyMap();
        }
    }

    private boolean refreshTableDenylist(String keyspace, String table)
    {
        checkDenylistNodeAvailability();
        final TableId tid = getTableId(keyspace, table);
        if (tid == null)
        {
            logger.warn("Got denylist mutation for unknown ks/cf: {}/{}. Skipping refresh.", keyspace, table);
            return false;
        }

        DenylistEntry newEntry = getDenylistForTableFromCQL(tid);
        denylist.put(tid, newEntry);
        return true;
    }

    private TableId getTableId(final String keyspace, final String table)
    {
        TableMetadata tmd = Schema.instance.getTableMetadata(keyspace, table);
        return tmd == null ? null : tmd.id;
    }
}

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Verify the keyspace/table names used in the denylist mutation exist (system_schema.tables)
  2. Remove stale denylist entries referencing dropped tables from system_distributed.partition_denylist
  3. Re-apply the denylist mutation after (re)creating the table, or rely on next full reload
  4. Fix typos in the denylist update call (JMX mbean / API parameters)

Example fix

// before
Denylist.addKeyToDenylist("ks","old_table", pk); // table dropped
// after
if (Schema.instance.isValidTable("ks","old_table")) Denylist.addKeyToDenylist("ks","old_table", pk);
Defensive patterns

Strategy: validation

Validate before calling

// confirm table exists before denylist mutation
if (Schema.instance.getTableMetadataNullable(keyspace, table) == null)
    throw new IllegalArgumentException("Unknown ks/cf for denylist mutation: " + keyspace + "/" + table);

Type guard

boolean tableExists(String ks, String cf) {
    return ClusterMetadata.current().schema.getKeyspaceMetadata(ks) != null
        && ClusterMetadata.current().schema.getKeyspaceMetadata(ks).getTableOrViewNullable(cf) != null;
}

Try / catch

if (!refreshTableDenylist(ks, table)) {
    logger.warn("Denylist refresh skipped for missing table {}/{}", ks, table);
}

Prevention

When it happens

Trigger: addKeyToDenylist or removeKeyFromDenylist invoked for a ks/cf name that no longer exists (dropped table/keyspace) or never existed when the denylist mutation is processed.

Common situations: Stale denylist entries referencing dropped tables after schema changes; race between DROP TABLE and a denylist write; typo in keyspace/table name in denylist JMX/API calls.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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