puppetlabs/puppet · error · Puppet::Error

#{label} has no value

Error message

#{label} has no value

What it means

PAttribute tracks 'no value' with the internal sentinel :undef because nil is a perfectly valid default value. Calling #value on an attribute that has no default therefore cannot return nil; it raises Puppet::Error. The companion predicate #value? (true unless the value is :undef) exists exactly for this check.

Source

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

    # @return [Booelan] true if the given value equals the default value for this attribute
    def default_value?(value)
      @value == value
    end

    # @return [Boolean] `true` if a value has been defined for this attribute.
    def value?
      @value != :undef
    end

    # Returns the value of this attribute, or raises an error if no value has been defined. Raising an error
    # is necessary since a defined value may be `nil`.
    #
    # @return [Object] the value that has been defined for this attribute.
    # @raise [Puppet::Error] if no value has been defined
    # @api public
    def value
      # An error must be raised here since `nil` is a valid value and it would be bad to leak the :undef symbol
      raise Puppet::Error, "#{label} has no value" if @value == :undef

      @value
    end

    # @api private
    def self.feature_type
      'attribute'
    end
  end

  class PTypeParameter < PAttribute
    # @return [Hash{String=>Object}] the hash
    # @api private
    def _pcore_init_hash
      hash = super
      hash[KEY_TYPE] = hash[KEY_TYPE].type
      hash.delete(KEY_VALUE) if hash.include?(KEY_VALUE) && hash[KEY_VALUE].nil?
      hash

View on GitHub (pinned to e227c27540)

Solutions

  1. Guard the access: attr.value? ? attr.value : nil (or your own sentinel/behavior).
  2. Filter first: type.attributes.values.select(&:value?).each { |a| use a.value }.
  3. Never test @value/nil yourself — the :undef sentinel must not leak into user code.

Example fix

# before
type.attributes.each_value { |a| defaults[a.name] = a.value }

# after
type.attributes.each_value { |a| defaults[a.name] = a.value if a.value? }
Defensive patterns

Strategy: type-guard

Validate before calling

# Ruby — always pair the predicate with the accessor
value = attr.value? ? attr.value : my_default

Type guard

def attribute_value_or(attr, fallback = nil)
  attr.value? ? attr.value : fallback
end

Try / catch

begin
  a.value
rescue Puppet::Error
  nil # attribute has no default; handle accordingly
end

Prevention

When it happens

Trigger: Ruby code that walks an Object type's attributes and calls attr.value unconditionally — e.g. tooling that builds documentation, forms, or serializers from type definitions, encountering attributes of kind 'derived'/'given_or_derived' or plain attributes without defaults.

Common situations: Generic reflection over Puppet::Pops::Types::PObjectType attributes that assumes every attribute has a default; mixing up #value (raises when absent) with #value? (predicate).

Related errors


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