puppetlabs/puppet · error · Puppet::ParseError

%{label} equality is referencing %{attribute} which is inclu

Error message

%{label} equality is referencing %{attribute} which is included in equality of %{including_parent}

What it means

When a child type declares an explicit equality list, each referenced attribute that exists in the parent is checked against the parent's equality_attributes. Re-listing an attribute that the parent's equality already includes would make the child's equality ambiguous, so Puppet::ParseError is raised naming both the child and the type ('including_parent') whose equality already contains the attribute.

Source

Thrown at lib/puppet/pops/types/p_object_type.rb:801

    equality = init_hash[KEY_EQUALITY]
    equality = [equality] if equality.is_a?(String)
    if equality.is_a?(Array)
      unless equality.empty?
        # TRANSLATORS equality_include_type = false should not be translated
        raise Puppet::ParseError, _('equality_include_type = false cannot be combined with non empty equality specification') unless @equality_include_type

        parent_eq_attrs = nil
        equality.each do |attr_name|
          attr = parent_members[attr_name]
          if attr.nil?
            attr = @attributes[attr_name] || @functions[attr_name]
          elsif attr.is_a?(PAttribute)
            # Assert that attribute is not already include by parent equality
            parent_eq_attrs ||= parent_object_type.equality_attributes
            if parent_eq_attrs.include?(attr_name)
              including_parent = find_equality_definer_of(attr)
              raise Puppet::ParseError, _("%{label} equality is referencing %{attribute} which is included in equality of %{including_parent}") %
                                        { label: label, attribute: attr.label, including_parent: including_parent.label }
            end
          end

          unless attr.is_a?(PAttribute)
            if attr.nil?
              raise Puppet::ParseError, _("%{label} equality is referencing non existent attribute '%{attribute}'") % { label: label, attribute: attr_name }
            end

            raise Puppet::ParseError, _("%{label} equality is referencing %{attribute}. Only attribute references are allowed") %
                                      { label: label, attribute: attr.label }
          end
          if attr.kind == ATTRIBUTE_KIND_CONSTANT
            raise Puppet::ParseError, _("%{label} equality is referencing constant %{attribute}.") % { label: label, attribute: attr.label } + ' ' +
                                      _("Reference to constant is not allowed in equality")
          end
        end
      end

View on GitHub (pinned to e227c27540)

Solutions

  1. In the child's equality list, reference only attributes new to the child; inherited attributes already in the parent's equality are automatically covered
  2. If the parent should no longer own that attribute's equality, move the equality declaration down: remove it from the parent and declare it in the child

Example fix

# before
type MyApp::Base = Object[{ equality => ['a'] }]
type MyApp::Child = Object[{
  parent => 'MyApp::Base',
  equality => ['a', 'b']      # 'a' already in MyApp::Base equality
}]

# after
type MyApp::Child = Object[{
  parent => 'MyApp::Base',
  equality => ['b']
}]
Defensive patterns

Strategy: validation

Validate before calling

# before declaring child equality, check the parent's equality attributes
parent_eq = parent_object_type.equality_attributes
repeated = declared_equality & parent_eq.map { |a| a.name }
raise "attributes already in parent equality: #{repeated.inspect}" unless repeated.empty?

Try / catch

begin
  Puppet::Pops::Types::PObjectType.new(name, init_hash)
rescue Puppet::ParseError => e
  raise unless e.message =~ /which is included in equality of/
  raise  # e.message names both types; drop the inherited attribute from the child list
end

Prevention

When it happens

Trigger: Parent declares equality => ['a']; child declares parent => Parent together with equality => ['a', 'b']. The 'a' entry resolves to a parent PAttribute already present in parent_object_type.equality_attributes, triggering the raise. Trigger also fires for deeper ancestry since find_equality_definer_of walks up.

Common situations: Extending a base type and copy-pasting its equality list into the child; refactoring a type hierarchy where equality was previously duplicated across levels.

Related errors


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