{"record":{"id":"55dbd6e1b931e2f9","repo":"puppetlabs/puppet","slug":"attribute-label-key-is-defined-as-both-a-co","errorCode":null,"errorMessage":"attribute %{label}[%{key}] is defined as both a constant and an attribute","messagePattern":"attribute %(.+?)\\[%(.+?)\\] is defined as both a constant and an attribute","errorType":"exception","errorClass":"Puppet::ParseError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_object_type.rb","lineNumber":742,"sourceCode":"        end\n        param_type = POptionalType.new(param_type) unless param_type.is_a?(POptionalType)\n        type_param = PTypeParameter.new(key, self, KEY_TYPE => param_type, KEY_VALUE => param_value).assert_override(parent_type_params)\n        @type_parameters[key] = type_param\n      end\n    end\n\n    constants = init_hash[KEY_CONSTANTS]\n    attr_specs = init_hash[KEY_ATTRIBUTES]\n    if attr_specs.nil?\n      attr_specs = {}\n    else\n      # attr_specs might be frozen\n      attr_specs = attr_specs.to_h\n    end\n    unless constants.nil? || constants.empty?\n      constants.each do |key, value|\n        if attr_specs.include?(key)\n          raise Puppet::ParseError, _(\"attribute %{label}[%{key}] is defined as both a constant and an attribute\") % { label: label, key: key }\n        end\n\n        attr_spec = {\n          # Type must be generic here, or overrides would become impossible\n          KEY_TYPE => TypeCalculator.infer(value).generalize,\n          KEY_VALUE => value,\n          KEY_KIND => ATTRIBUTE_KIND_CONSTANT\n        }\n        # Indicate override if parent member exists. Type check etc. will take place later on.\n        attr_spec[KEY_OVERRIDE] = parent_members.include?(key)\n        attr_specs[key] = attr_spec\n      end\n    end\n\n    unless attr_specs.empty?\n      @attributes = attr_specs.to_h do |key, attr_spec|\n        unless attr_spec.is_a?(Hash)\n          attr_type = TypeAsserter.assert_instance_of(nil, PTypeType::DEFAULT, attr_spec) { \"attribute #{label}[#{key}]\" }","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_object_type.rb#L724-L760","documentation":"In an Object type definition, entries under constants are folded into the attribute map as constant-kind attributes. Before doing so, Puppet checks that no key appears in both constants and attributes; a Puppet::ParseError is raised because the two declarations would conflict over the same member name.","triggerScenarios":"A type definition hash containing the same key in both blocks, e.g. attributes => { mode => String } and constants => { mode => 'read' }. Reachable from Puppet DSL type declarations, Ruby PObjectType init hashes, and pcore-loaded type definitions.","commonSituations":"Promoting a constant to a real attribute (or vice versa) and forgetting to delete the old block; merging type definitions programmatically; copy-paste between type definitions.","solutions":["Pick one form: if the value should be settable per instance, keep it in attributes and delete it from constants; if fixed forever, keep only constants","Run puppet parser validate or a catalog compile to catch it before deployment"],"exampleFix":"# before\ntype MyApp::Cfg = Object[{\n  attributes => { mode => String },\n  constants => { mode => 'read' }\n}]\n\n# after\ntype MyApp::Cfg = Object[{\n  attributes => { mode => String[1] }\n}]","handlingStrategy":"validation","validationCode":"# before building the init hash / shipping a type definition\noverlap = (constants.keys & attributes.keys)\nraise \"keys declared both constant and attribute: #{overlap.inspect}\" unless overlap.empty?","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::Pops::Types::PObjectType.new(name, init_hash)\nrescue Puppet::ParseError => e\n  raise unless e.message =~ /defined as both a constant and an attribute/\n  raise  # e.message names the offending key; remove it from one block\nend","preventionTips":["When promoting a constant to an attribute (or the reverse), delete the other block in the same edit","Validate type definitions with puppet parser validate before deploy","If generating type hashes programmatically, assert the attributes/constants key sets are disjoint"],"tags":["puppet","pcore","object-type","duplicate-key","schema"],"backgroundTag":"duplicate-key-definition","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}