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

  1. 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.
  2. Flatten the configurations: give each entry a direct class_name instead of chained inheritance.
  3. 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

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


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