puppetlabs/puppet · error · Puppet::Error
The Object type '#{originator.label}' inherits from itself
Error message
The Object type '#{originator.label}' inherits from itself What it means
Before resolving an Object type's parent chain, check_self_recursion walks upward through @parent links and raises Puppet::Error if the chain returns to the type that started the walk. Both direct self-parenting (parent => own name) and longer cycles (A's parent is B, B's parent is A) are caught.
Source
Thrown at lib/puppet/pops/types/p_object_type.rb:1005
@equality_include_type
end
# Returns the functions of this `Object` type. If _include_parent_ is `true`, then all
# inherited functions will be included in the returned `Hash`.
#
# @param include_parent [Boolean] `true` if inherited functions should be included
# @return [Hash{String=>PFunction}] a hash with the functions
# @api public
def functions(include_parent = false)
get_members(include_parent, :functions)
end
DEFAULT = PObjectType.new(EMPTY_HASH)
# Assert that this type does not inherit from itself
# @api private
def check_self_recursion(originator)
unless @parent.nil?
raise Puppet::Error, "The Object type '#{originator.label}' inherits from itself" if @parent.equal?(originator)
@parent.check_self_recursion(originator)
end
end
# @api private
def label
@name || 'Object'
end
# @api private
def resolved_parent
parent = @parent
while parent.is_a?(PTypeAliasType)
parent = parent.resolved_type
end
parent
endView on GitHub (pinned to e227c27540)
Solutions
- Inspect the parent declarations of every type named in the error and break the loop: a type must ultimately derive from Object or another acyclic base
- If you cloned a type, change the clone's parent to the actual base type
- For generated code, emit a topological ordering check so cycles are caught at generation time
Example fix
# before
type MyApp::Node = Object[{
parent => 'MyApp::Node', # inherits from itself
attributes => { name => String }
}]
# after
type MyApp::Node = Object[{
parent => 'MyApp::Base',
attributes => { name => String }
}] Defensive patterns
Strategy: validation
Validate before calling
# walk the parent chain and detect cycles before resolution
def cyclic?(type, seen = {})
parent = type.instance_variable_get(:@parent)
return false if parent.nil?
return true if seen.key?(parent.label)
seen[type.label] = true
cyclic?(parent, seen)
end
raise 'parent cycle detected' if cyclic?(my_type) Try / catch
begin Puppet::Pops::Types::PObjectType.new(name, init_hash) rescue Puppet::Error => e raise unless e.message =~ /inherits from itself/ raise # e.message names the loop head; break the parent cycle end
Prevention
- After cloning or renaming types, grep all parent => references for self-links
- For generated type hierarchies, topologically sort before emitting definitions
When it happens
Trigger: type MyApp::Node = Object[{ parent => 'MyApp::Node', ... }] (self-reference, often a copy-paste artifact), or two types in different files each naming the other as parent. The check runs during type resolution, before members are merged.
Common situations: Cloning a type definition and forgetting to update the parent; renaming types so old parent references now point at each other; generated type hierarchies emitted with cyclic parent links.
Related errors
- reference to unresolved type '%{name}'
- %{label} equality is referencing %{attribute} which is inclu
- expected %{label} to override an inherited %{feature_type},
- %{member} attempts to override %{label}
- %{member} attempts to override final %{label}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/04467b2f5cc86572.
Report an issue: GitHub.