puppetlabs/puppet · error · Puppet::ParseError

The attribute '%{name}' is reserved and cannot be used

Error message

The attribute '%{name}' is reserved and cannot be used

What it means

The keys '__ptype' and '__pvalue' (Serialization::PCORE_TYPE_KEY and PCORE_VALUE_KEY) carry the type tag and payload in Puppet's serialized PCore format, so an Object type attribute may not use either name — allowing it would make serialized output ambiguous. PAttribute#initialize raises this Puppet::ParseError immediately.

Source

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

  end

  # Describes a named Attribute in an Object type
  # @api public
  class PAttribute < PAnnotatedMember
    # @return [String,nil] The attribute kind as defined by #TYPE_ATTRIBUTE_KIND, or `nil`
    attr_reader :kind

    # @param name [String] The name of the attribute
    # @param container [PObjectType] The containing object type
    # @param init_hash [Hash{String=>Object}] Hash containing attribute options
    # @option init_hash [PAnyType] 'type' The attribute type (required)
    # @option init_hash [Object] 'value' The default value, must be an instanceof the given `type` (optional)
    # @option init_hash [String] 'kind' The attribute kind, matching #TYPE_ATTRIBUTE_KIND
    # @api public
    def initialize(name, container, init_hash)
      super(name, container, TypeAsserter.assert_instance_of(nil, TYPE_ATTRIBUTE, init_hash) { "initializer for #{self.class.label(container, name)}" })
      if name == Serialization::PCORE_TYPE_KEY || name == Serialization::PCORE_VALUE_KEY
        raise Puppet::ParseError, _("The attribute '%{name}' is reserved and cannot be used") % { name: name }
      end

      @kind = init_hash[KEY_KIND]
      if @kind == ATTRIBUTE_KIND_CONSTANT # final is implied
        if init_hash.include?(KEY_FINAL) && !@final
          # TRANSLATOR 'final => false' is puppet syntax and should not be translated
          raise Puppet::ParseError, _("%{label} of kind 'constant' cannot be combined with final => false") % { label: label }
        end

        @final = true
      end

      if init_hash.include?(KEY_VALUE)
        if @kind == ATTRIBUTE_KIND_DERIVED || @kind == ATTRIBUTE_KIND_GIVEN_OR_DERIVED
          raise Puppet::ParseError, _("%{label} of kind '%{kind}' cannot be combined with an attribute value") % { label: label, kind: @kind }
        end

        v = init_hash[KEY_VALUE]

View on GitHub (pinned to e227c27540)

Solutions

  1. Rename the attribute to anything else (e.g. 'pcore_type' / 'pvalue_').
  2. If names come from external data, filter reserved keys ('__ptype', '__pvalue') during generation with an allowlist/prefix strategy.
  3. Keep serialization metadata out of your domain attributes; model only real data fields.

Example fix

# before
type Rec = Object[{'attributes' => {'__ptype' => String}}]

# after
type Rec = Object[{'attributes' => {'pcore_type_name' => String}}]
Defensive patterns

Strategy: validation

Validate before calling

# Ruby — filter reserved keys when generating attribute names
RESERVED = [Puppet::Pops::Serialization::PCORE_TYPE_KEY, Puppet::Pops::Serialization::PCORE_VALUE_KEY].freeze
fail("attribute name #{n} is reserved") if RESERVED.include?(n)

Type guard

def usable_attribute_name?(name)
  name != '__ptype' && name != '__pvalue'
end

Prevention

When it happens

Trigger: An Object type declaration with attributes => {'__ptype' => ...} or {'__pvalue' => ...}, typically when attribute names are generated mechanically from external data (JSON schemas, DB columns, message field names) that happen to contain those keys.

Common situations: Codegen that derives Puppet Object types from external schemas without filtering reserved names; round-tripping serialized PCore hashes back into type definitions.

Related errors


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