puppetlabs/puppet · error · Puppet::Error

The Object type '# ' 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.

Solutions

  1. 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
  2. If you cloned a type, change the clone's parent to the actual base type
  3. 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

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


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/04467b2f5cc86572. Report an issue: GitHub.

Appendix: 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
  end

View on GitHub (pinned to e227c27540)