apache/cassandra · error · ConfigurationException
Detected loop when processing key %s
Error message
Detected loop when processing key %s
What it means
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.
Source
Thrown at src/java/org/apache/cassandra/schema/MemtableParams.java:182
inheritingClasses.put(entry.getKey(), entry.getValue());
}
else
configs.put(entry.getKey(), entry.getValue().resolve(configs));
}
for (Map.Entry<String, InheritingClass> inheritingEntry : inheritingClasses.entrySet())
{
String inherits = inheritingEntry.getValue().inherits;
while (inherits != null)
{
InheritingClass nextInheritance = inheritingClasses.get(inherits);
if (nextInheritance == null)
inherits = null;
else
inherits = nextInheritance.inherits;
if (inherits != null && inherits.equals(inheritingEntry.getKey()))
throw new ConfigurationException(String.format("Detected loop when processing key %s", inheritingEntry.getKey()));
}
}
while (!inheritingClasses.isEmpty())
{
Set<String> forRemoval = new HashSet<>();
for (Map.Entry<String, InheritingClass> inheritingEntry : inheritingClasses.entrySet())
{
if (configs.get(inheritingEntry.getValue().inherits) != null)
{
configs.put(inheritingEntry.getKey(), inheritingEntry.getValue().resolve(configs));
forRemoval.add(inheritingEntry.getKey());
}
}
assert !forRemoval.isEmpty();
for (String toRemove : forRemoval)View on GitHub (pinned to 88fd0f6a0e)
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.
Example fix
# before (cassandra.yaml)
memtable_configurations:
a: {inherits: b, class_name: X}
b: {inherits: a, class_name: Y} # cycle
# after
memtable_configurations:
a: {inherits: default, class_name: X}
b: {inherits: default, class_name: Y} Defensive patterns
Strategy: validation
Validate before calling
static void assertNoInheritCycle(Map<String,InheritingClass> cfg) {
for (String k : cfg.keySet()) {
Set<String> seen = new HashSet<>();
String cur = k;
while (cur != null && cfg.containsKey(cur)) {
if (!seen.add(cur)) throw new IllegalStateException("inherit cycle at " + cur);
cur = cfg.get(cur).inherits;
}
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- data_file_directories must not contain empty entry
- Configuration entry %s can not inherit itself.
- Configuration entry %s inherits non-existing entry %s.
- The 'class_name' option must be specified.
- memtable_cleanup_threshold has been deprecated and should be
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/4740157b7fa9863a.
Report an issue: GitHub.