{"record":{"id":"cbcf8d3bb6d7a333","repo":"apache/cassandra","slug":"attempting-to-load-denylist-and-not-enough-nodes-a","errorCode":null,"errorMessage":"Attempting to load denylist and not enough nodes are available for a {} refresh. Reload the denylist when unavailable nodes are recovered to ensure your denylist remains in sync.","messagePattern":"Attempting to load denylist and not enough nodes are available for a (.+?) refresh\\. Reload the denylist when unavailable nodes are recovered to ensure your denylist remains in sync\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/schema/PartitionDenylist.java","lineNumber":181,"sourceCode":"        int retryInSeconds = DatabaseDescriptor.getDenylistInitialLoadRetrySeconds();\n        logger.info(\"{} while loading partition denylist cache. Scheduled retry in {} seconds.\", retryReason, retryInSeconds);\n        ScheduledExecutors.optionalTasks.schedule(this::initialLoad, retryInSeconds, TimeUnit.SECONDS);\n    }\n\n    private boolean checkDenylistNodeAvailability()\n    {\n        TableMetadata denyListTable = ClusterMetadata.current().schema.getKeyspaceMetadata(SystemDistributedKeyspace.NAME)\n                                                              .getTableOrViewNullable(SystemDistributedKeyspace.PARTITION_DENYLIST_TABLE);\n        if (denyListTable == null)\n        {\n            logger.warn(\"Partition denylist table metadata not found\");\n            return false;\n        }\n\n        boolean sufficientNodes = RangeCommands.sufficientLiveNodesForSelectStar(denyListTable, DatabaseDescriptor.getDenylistConsistencyLevel());\n        if (!sufficientNodes)\n        {\n            AVAILABILITY_LOGGER.warn(\"Attempting to load denylist and not enough nodes are available for a {} refresh. Reload the denylist when unavailable nodes are recovered to ensure your denylist remains in sync.\",\n                                     DatabaseDescriptor.getDenylistConsistencyLevel());\n        }\n        return sufficientNodes;\n    }\n\n    /** Helper method as we need to both build cache on initial init but also on reload of cache contents and params */\n    private LoadingCache<TableId, DenylistEntry> buildEmptyCache()\n    {\n        // We rely on details of .refreshAfterWrite to reload this async in the background when it's hit:\n        // https://github.com/ben-manes/caffeine/wiki/Refresh\n        return Caffeine.newBuilder()\n                       .refreshAfterWrite(DatabaseDescriptor.getDenylistRefreshSeconds(), TimeUnit.SECONDS)\n                       .executor(executor)\n                       .build(new CacheLoader<TableId, DenylistEntry>()\n                       {\n                           @Override\n                           public DenylistEntry load(final TableId tid)\n                           {","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/schema/PartitionDenylist.java#L163-L199","documentation":"PartitionDenylist.checkDenylistNodeAvailability logs this warning when there are not enough live nodes to satisfy the configured denylist consistency level for a SELECT * over the denylist table. It returns the insufficiency (false) to callers, meaning the denylist cannot be refreshed at this time.","triggerScenarios":"Denylist load/reload/refresh attempted while live node count is below RangeCommands.sufficientLiveNodesForSelectStar for DatabaseDescriptor.getDenylistConsistencyLevel() (e.g. QUORUM with nodes down).","commonSituations":"Nodes down or decommissioned during denylist refresh; clusters operating at reduced capacity after outages; overly strong denylist_consistency_level relative to cluster size (e.g. EACH_QUORUM in a multi-DC setup).","solutions":["Recover/restart the unavailable nodes, then reload the denylist as the message advises","Lower cassandra.denylist_consistency_level (e.g. from QUORUM to LOCAL_QUORUM or ONE) if the current level exceeds cluster capacity","Run nodetool status to identify and fix down nodes / replication gaps","Re-trigger denylist reload (nodetool reload PartitionDenylist / restart) after capacity returns"],"exampleFix":"// before\ncassandra.denylist_consistency_level: EACH_QUORUM  # requires all DCs healthy\n// after\ncassandra.denylist_consistency_level: LOCAL_QUORUM # tolerant of remote-DC outage","handlingStrategy":"fallback","validationCode":"boolean canRefresh = RangeCommands.sufficientLiveNodesForSelectStar(\n    denyListTable, DatabaseDescriptor.getDenylistConsistencyLevel());\nif (!canRefresh) {\n    logger.warn(\"Deferring denylist refresh; will retry when nodes recover\");\n    scheduleDenylistRetry();\n}","typeGuard":null,"tryCatchPattern":"// method returns false when nodes insufficient; handle explicitly\nif (!denylist.checkDenylistNodeAvailability()) {\n    // serve stale denylist from cache until nodes recover\n    return;\n}","preventionTips":["Size the cluster so the configured denylist consistency level is achievable during partial outages","Lower denylist_consistency_level if it exceeds cluster/DC capacity","Schedule denylist reloads to retry automatically when nodes recover","Monitor nodetool status for down nodes"],"tags":["denylist","consistency","availability","nodes-down"],"backgroundTag":"insufficient-live-nodes","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}