netdata/netdata · error · ConstructorError
found unconstructable recursive node
Error message
found unconstructable recursive node
What it means
Raised by BaseConstructor.construct_object when a node is re-entered while it is still being constructed (it sits in self.recursive_objects). This happens with self-referential structures whose constructor cannot be expressed incrementally — typically when a recursive node appears where a fully constructed object is required, e.g. as a mapping key or inside deep construction of non-generator constructors.
Source
Thrown at src/collectors/python.d.plugin/python_modules/pyyaml3/constructor.py:61
while self.state_generators:
state_generators = self.state_generators
self.state_generators = []
for generator in state_generators:
for dummy in generator:
pass
self.constructed_objects = {}
self.recursive_objects = {}
self.deep_construct = False
return data
def construct_object(self, node, deep=False):
if node in self.constructed_objects:
return self.constructed_objects[node]
if deep:
old_deep = self.deep_construct
self.deep_construct = True
if node in self.recursive_objects:
raise ConstructorError(None, None,
"found unconstructable recursive node", node.start_mark)
self.recursive_objects[node] = None
constructor = None
tag_suffix = None
if node.tag in self.yaml_constructors:
constructor = self.yaml_constructors[node.tag]
else:
for tag_prefix in self.yaml_multi_constructors:
if node.tag.startswith(tag_prefix):
tag_suffix = node.tag[len(tag_prefix):]
constructor = self.yaml_multi_constructors[tag_prefix]
break
else:
if None in self.yaml_multi_constructors:
tag_suffix = node.tag
constructor = self.yaml_multi_constructors[None]
elif None in self.yaml_constructors:
constructor = self.yaml_constructors[None]View on GitHub (pinned to 4864de85e2)
Solutions
- Remove the self-reference from the YAML — express shared data with ordinary aliases to a fully-defined node instead of a cyclic one.
- If cyclic data is genuinely needed, use objects and a custom constructor with two-step (generator-based) construction, or build the cycle in Python after loading.
- Check whether the recursion is accidental (an alias at the wrong indentation pointing at its own parent) and fix the alias target.
Example fix
# before (cyclic -> unconstructable)
a: &x
b: *x
# after (acyclic sharing)
base: &base {v: 1}
a:
b: *base Defensive patterns
Strategy: try-catch
Validate before calling
import yaml
def has_recursive_nodes(text):
def walk(node, seen):
if id(node) in seen:
return True
seen = seen | {id(node)}
if isinstance(node, yaml.MappingNode):
return any(walk(k, seen) or walk(v, seen) for k, v in node.value)
if isinstance(node, yaml.SequenceNode):
return any(walk(c, seen) for c in node.value)
return False
return walk(yaml.compose(text), frozenset()) Try / catch
try:
cfg = yaml.safe_load(text)
except yaml.ConstructorError as e:
if 'unconstructable recursive node' in str(e):
reject_config('cyclic YAML structures are not supported')
raise Prevention
- Keep config YAML strictly acyclic; model shared data with plain aliases to complete nodes.
- Build cyclic object graphs in Python after loading, not in the YAML.
- Reject self-referential snippets in config validation with a clear message.
When it happens
Trigger: Self-referential YAML such as '&a {b: *a}' used as a mapping key, or 'a: &x\n b: *x' combined with constructors that build eagerly (deep=True), so the alias is resolved before the parent object exists.
Common situations: Hand-written YAML that models linked/cyclic data (trees with parent links); users copying recursive YAML examples into configs parsed by SafeConstructor; using yaml.compose on cyclic data then constructing with non-safe constructors.
Related errors
- found undefined alias %r
- expected a mapping or list of mappings for merging, but foun
- extra_yaml is not valid YAML: {exc}
- extra_yaml must be a YAML mapping, got {type(extra).__name__
- expected a single document in the stream
AI-assisted analysis of netdata/netdata@4864de85e2 (2026-08-15).
Data as JSON: /api/errors/45682760621d2eed.
Report an issue: GitHub.