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
  end

View on GitHub (pinned to e227c27540)

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.