{"record":{"id":"8d6793a565e2a4f9","repo":"puppetlabs/puppet","slug":"label-equality-is-referencing-attribute-whic","errorCode":null,"errorMessage":"%{label} equality is referencing %{attribute} which is included in equality of %{including_parent}","messagePattern":"%(.+?) equality is referencing %(.+?) which is included in equality of %(.+?)","errorType":"exception","errorClass":"Puppet::ParseError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_object_type.rb","lineNumber":801,"sourceCode":"\n    equality = init_hash[KEY_EQUALITY]\n    equality = [equality] if equality.is_a?(String)\n    if equality.is_a?(Array)\n      unless equality.empty?\n        # TRANSLATORS equality_include_type = false should not be translated\n        raise Puppet::ParseError, _('equality_include_type = false cannot be combined with non empty equality specification') unless @equality_include_type\n\n        parent_eq_attrs = nil\n        equality.each do |attr_name|\n          attr = parent_members[attr_name]\n          if attr.nil?\n            attr = @attributes[attr_name] || @functions[attr_name]\n          elsif attr.is_a?(PAttribute)\n            # Assert that attribute is not already include by parent equality\n            parent_eq_attrs ||= parent_object_type.equality_attributes\n            if parent_eq_attrs.include?(attr_name)\n              including_parent = find_equality_definer_of(attr)\n              raise Puppet::ParseError, _(\"%{label} equality is referencing %{attribute} which is included in equality of %{including_parent}\") %\n                                        { label: label, attribute: attr.label, including_parent: including_parent.label }\n            end\n          end\n\n          unless attr.is_a?(PAttribute)\n            if attr.nil?\n              raise Puppet::ParseError, _(\"%{label} equality is referencing non existent attribute '%{attribute}'\") % { label: label, attribute: attr_name }\n            end\n\n            raise Puppet::ParseError, _(\"%{label} equality is referencing %{attribute}. Only attribute references are allowed\") %\n                                      { label: label, attribute: attr.label }\n          end\n          if attr.kind == ATTRIBUTE_KIND_CONSTANT\n            raise Puppet::ParseError, _(\"%{label} equality is referencing constant %{attribute}.\") % { label: label, attribute: attr.label } + ' ' +\n                                      _(\"Reference to constant is not allowed in equality\")\n          end\n        end\n      end","sourceCodeStart":783,"sourceCodeEnd":819,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_object_type.rb#L783-L819","documentation":"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.","triggerScenarios":"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.","commonSituations":"Extending a base type and copy-pasting its equality list into the child; refactoring a type hierarchy where equality was previously duplicated across levels.","solutions":["In the child's equality list, reference only attributes new to the child; inherited attributes already in the parent's equality are automatically covered","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"],"exampleFix":"# before\ntype MyApp::Base = Object[{ equality => ['a'] }]\ntype MyApp::Child = Object[{\n  parent => 'MyApp::Base',\n  equality => ['a', 'b']      # 'a' already in MyApp::Base equality\n}]\n\n# after\ntype MyApp::Child = Object[{\n  parent => 'MyApp::Base',\n  equality => ['b']\n}]","handlingStrategy":"validation","validationCode":"# before declaring child equality, check the parent's equality attributes\nparent_eq = parent_object_type.equality_attributes\nrepeated = declared_equality & parent_eq.map { |a| a.name }\nraise \"attributes already in parent equality: #{repeated.inspect}\" unless repeated.empty?","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::Pops::Types::PObjectType.new(name, init_hash)\nrescue Puppet::ParseError => e\n  raise unless e.message =~ /which is included in equality of/\n  raise  # e.message names both types; drop the inherited attribute from the child list\nend","preventionTips":["In child types, list only newly introduced attributes in equality","When refactoring hierarchies, review equality declarations top-down so each attribute has exactly one equality definer"],"tags":["puppet","pcore","object-type","equality","inheritance"],"backgroundTag":"inherited-member-conflict","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}