{"record":{"id":"bff006af64f81ebc","repo":"apache/cassandra","slug":"rowcachekeystosave-must-be-non-negative","errorCode":null,"errorMessage":"RowCacheKeysToSave must be non-negative.","messagePattern":"RowCacheKeysToSave must be non-negative\\.","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/CacheService.java","lineNumber":245,"sourceCode":"\n    public void setCounterCacheSavePeriodInSeconds(int seconds)\n    {\n        if (seconds < 0)\n            throw new RuntimeException(\"CounterCacheSavePeriodInSeconds must be non-negative.\");\n\n        DatabaseDescriptor.setCounterCacheSavePeriod(seconds);\n        counterCache.scheduleSaving(seconds, DatabaseDescriptor.getCounterCacheKeysToSave());\n    }\n\n    public int getRowCacheKeysToSave()\n    {\n        return DatabaseDescriptor.getRowCacheKeysToSave();\n    }\n\n    public void setRowCacheKeysToSave(int count)\n    {\n        if (count < 0)\n            throw new RuntimeException(\"RowCacheKeysToSave must be non-negative.\");\n        DatabaseDescriptor.setRowCacheKeysToSave(count);\n        rowCache.scheduleSaving(getRowCacheSavePeriodInSeconds(), count);\n    }\n\n    public int getKeyCacheKeysToSave()\n    {\n        return DatabaseDescriptor.getKeyCacheKeysToSave();\n    }\n\n    public void setKeyCacheKeysToSave(int count)\n    {\n        if (count < 0)\n            throw new RuntimeException(\"KeyCacheKeysToSave must be non-negative.\");\n        DatabaseDescriptor.setKeyCacheKeysToSave(count);\n        keyCache.scheduleSaving(getKeyCacheSavePeriodInSeconds(), count);\n    }\n\n    public int getCounterCacheKeysToSave()","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/CacheService.java#L227-L263","documentation":"CacheService.setRowCacheKeysToSave limits how many row-cache keys are written per save cycle; a negative count is meaningless and rejected with an untyped RuntimeException before the value is stored and the row cache saver rescheduled. Reached mainly through the CacheService JMX mbean.","triggerScenarios":"Calling setRowCacheKeysToSave(count) with count < 0 via JMX or internal code.","commonSituations":"Runtime tuning scripts computing the count from another metric that can be negative; manual JMX console edits; misread configuration keys where a sentinel like -1 (unlimited) is mistakenly assumed valid.","solutions":["Pass a non-negative count; 0 is the accepted way to limit saving behavior.","Clamp with Math.max(0, count) before the call.","If a sentinel for 'unlimited' was intended, use 0 or leave the cassandra.yaml value unchanged instead of a negative number.","Validate config-derived values before pushing them via JMX."],"exampleFix":"// before\ncacheService.setRowCacheKeysToSave(config.getSaveLimit()); // may be -1\n// after\nint count = Math.max(0, config.getSaveLimit());\ncacheService.setRowCacheKeysToSave(count);","handlingStrategy":"validation","validationCode":"if (count < 0) throw new IllegalArgumentException(\"RowCacheKeysToSave must be >= 0\");\ncacheService.setRowCacheKeysToSave(count);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not use -1 as an unlimited sentinel for cache settings in Cassandra.","Clamp metrics-derived values to zero floor before applying them.","Validate JMX console inputs before submission.","Keep tuning scripts idempotent and range-checked."],"tags":["jmx","configuration","cache","runtime-validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}