{"record":{"id":"4740157b7fa9863a","repo":"apache/cassandra","slug":"detected-loop-when-processing-key-s","errorCode":null,"errorMessage":"Detected loop when processing key %s","messagePattern":"Detected loop when processing key (.+?)","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/schema/MemtableParams.java","lineNumber":182,"sourceCode":"                inheritingClasses.put(entry.getKey(), entry.getValue());\n            }\n            else\n                configs.put(entry.getKey(), entry.getValue().resolve(configs));\n        }\n\n        for (Map.Entry<String, InheritingClass> inheritingEntry : inheritingClasses.entrySet())\n        {\n            String inherits = inheritingEntry.getValue().inherits;\n            while (inherits != null)\n            {\n                InheritingClass nextInheritance = inheritingClasses.get(inherits);\n                if (nextInheritance == null)\n                    inherits = null;\n                else\n                    inherits = nextInheritance.inherits;\n\n                if (inherits != null && inherits.equals(inheritingEntry.getKey()))\n                    throw new ConfigurationException(String.format(\"Detected loop when processing key %s\", inheritingEntry.getKey()));\n            }\n        }\n\n        while (!inheritingClasses.isEmpty())\n        {\n            Set<String> forRemoval = new HashSet<>();\n            for (Map.Entry<String, InheritingClass> inheritingEntry : inheritingClasses.entrySet())\n            {\n                if (configs.get(inheritingEntry.getValue().inherits) != null)\n                {\n                    configs.put(inheritingEntry.getKey(), inheritingEntry.getValue().resolve(configs));\n                    forRemoval.add(inheritingEntry.getKey());\n                }\n            }\n\n            assert !forRemoval.isEmpty();\n\n            for (String toRemove : forRemoval)","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/schema/MemtableParams.java#L164-L200","documentation":"Thrown from MemtableParams.expandDefinitions while resolving multi-level memtable configuration inheritance: walking the inherits chain from an entry eventually returns to the entry itself, forming a cycle (e.g. a inherits b, b inherits a). Such loops can never terminate, so Cassandra aborts with a ConfigurationException.","triggerScenarios":"cassandra.yaml memtable_configurations where two or more entries inherit each other (a.inherits=b and b.inherits=a, or a longer chain a->b->c->a); detected during chain expansion at startup.","commonSituations":"Incremental YAML edits over time accidentally closing an inheritance loop, config templating that injects inherits values from variables creating circular references, merging config files from different clusters.","solutions":["Trace the inherits chain from the key reported in the error and break the cycle by re-pointing the last link to 'default' or removing an inherits line.","Flatten the configurations: give each entry a direct class_name instead of chained inheritance.","Keep inheritance shallow (at most one level) to make cycles impossible in practice."],"exampleFix":"# before (cassandra.yaml)\nmemtable_configurations:\n  a: {inherits: b, class_name: X}\n  b: {inherits: a, class_name: Y}  # cycle\n# after\nmemtable_configurations:\n  a: {inherits: default, class_name: X}\n  b: {inherits: default, class_name: Y}","handlingStrategy":"validation","validationCode":"static void assertNoInheritCycle(Map<String,InheritingClass> cfg) {\n  for (String k : cfg.keySet()) {\n    Set<String> seen = new HashSet<>();\n    String cur = k;\n    while (cur != null && cfg.containsKey(cur)) {\n      if (!seen.add(cur)) throw new IllegalStateException(\"inherit cycle at \" + cur);\n      cur = cfg.get(cur).inherits;\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run a cycle check (DFS over inherits links) as part of config CI before shipping cassandra.yaml.","Keep inheritance depth to 1 to make cycles structurally impossible.","Treat memtable_configurations as code: review changes in PRs, not ad-hoc node edits."],"tags":["cassandra","configuration","yaml","cycle"],"backgroundTag":"invalid-config-value","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"}