{"record":{"id":"b6ae6fe5b6d2774f","repo":"puppetlabs/puppet","slug":"label-equality-is-referencing-attribute-onl","errorCode":null,"errorMessage":"%{label} equality is referencing %{attribute}. Only attribute references are allowed","messagePattern":"%(.+?) equality is referencing %(.+?)\\. Only attribute references are allowed","errorType":"exception","errorClass":"Puppet::ParseError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_object_type.rb","lineNumber":811,"sourceCode":"          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\n      equality.freeze\n    end\n    @equality = equality\n\n    @checks = init_hash[KEY_CHECKS]\n    init_annotatable(init_hash)\n  end\n\n  def [](name)\n    member = @attributes[name] || @functions[name]","sourceCodeStart":793,"sourceCodeEnd":829,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_object_type.rb#L793-L829","documentation":"An equality-list entry may resolve in the type's own members, which include both attributes and functions. If the resolved member is a PFunction rather than a PAttribute, Puppet::ParseError is raised: equality is defined over attribute values only, because functions have no per-instance value to compare.","triggerScenarios":"equality => ['greeting'] where greeting is declared under functions => { greeting => Callable[[], String] }. The lookup @attributes[attr_name] || @functions[attr_name] succeeds, but the member is not a PAttribute, so the raise fires.","commonSituations":"Trying to include a computed/derived value in equality by naming the function that computes it; type definitions where a function and the intended equality participant were confused.","solutions":["Reference an attribute instead: store the computed value in a real attribute (possibly derived at creation time) and list that attribute in equality","If the function wraps an attribute, list the underlying attribute"],"exampleFix":"# before\ntype MyApp::G = Object[{\n  attributes => { name => String },\n  functions => { greeting => Callable[[], String] },\n  equality => ['greeting']    # functions cannot participate in equality\n}]\n\n# after\ntype MyApp::G = Object[{\n  attributes => { name => String },\n  functions => { greeting => Callable[[], String] },\n  equality => ['name']\n}]","handlingStrategy":"validation","validationCode":"# equality entries must resolve to PAttribute instances, never PFunction\nbad = equality_list.reject { |n| (attrs[n] || parent_members[n]).is_a?(Puppet::Pops::Types::PAttribute) }\nraise \"equality references functions or non-attributes: #{bad.inspect}\" unless bad.empty?","typeGuard":"def attribute?(type, name)\n  member = type.attributes(true)[name] || (type.parent.respond_to?(:members) && type.parent.members(true)[name])\n  member.is_a?(Puppet::Pops::Types::PAttribute)\nend","tryCatchPattern":"begin\n  Puppet::Pops::Types::PObjectType.new(name, init_hash)\nrescue Puppet::ParseError => e\n  raise unless e.message =~ /Only attribute references are allowed/\n  raise  # e.message names the function; reference an attribute instead\nend","preventionTips":["Remember functions have no per-instance value and can never join equality","Materialize computed values into attributes if they must affect identity"],"tags":["puppet","pcore","object-type","equality","functions"],"backgroundTag":"invalid-equality-definition","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}