puppetlabs/puppet · error · Puppet::Error

Unable to create an instance of #{name}. #{class_name} does

Error message

Unable to create an instance of #{name}. #{class_name} does not include module #{PuppetObject.name}

What it means

A loaded implementation class for an Object type must either include Puppet::Pops::Types::PuppetObject (so instances support _pcore_type and PCore construction) or be an RGen metamodel class (responds to :ecore). If ClassLoader returns a class satisfying neither, Puppet::Error explains that the class does not include the PuppetObject module.

Source

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

    end
  end

  # @api private
  def implementation_class(create = true)
    if @implementation_class.nil? && create
      ir = Loaders.implementation_registry
      class_name = ir.nil? ? nil : ir.module_name_for_type(self)
      if class_name.nil?
        # Use generator to create a default implementation
        @implementation_class = RubyGenerator.new.create_class(self)
        @implementation_class.class_eval(&@implementation_override) if instance_variable_defined?(:@implementation_override)
      else
        # Can the mapping be loaded?
        @implementation_class = ClassLoader.provide(class_name)

        raise Puppet::Error, "Unable to load class #{class_name}" if @implementation_class.nil?
        unless @implementation_class < PuppetObject || @implementation_class.respond_to?(:ecore)
          raise Puppet::Error, "Unable to create an instance of #{name}. #{class_name} does not include module #{PuppetObject.name}"
        end
      end
    end
    @implementation_class
  end

  # @api private
  def implementation_class=(cls)
    raise ArgumentError, "attempt to redefine implementation class for #{label}" unless @implementation_class.nil?

    @implementation_class = cls
  end

  # The block passed to this method will be passed in a call to `#class_eval` on the dynamically generated
  # class for this data type. It's indended use is to complement or redefine the generated methods and
  # attribute readers.
  #
  # The method is normally called with the block passed to `#implementation` when a data type is defined using

View on GitHub (pinned to e227c27540)

Solutions

  1. In your implementation class, include Puppet::Pops::Types::PuppetObject (implementing _pcore_type / the standard constructor pattern, easiest via Puppet::DataTypes.create_type with an implementation block).
  2. If the class is an RGen/Ecore model class, respond to :ecore — that path is also accepted.
  3. Check the mapped name for collisions: ensure the registry entry points at the class you think it does (confirm with ClassLoader.provide in a Ruby shell).

Example fix

# before
class PuppetX::Mymod::Widget
  attr_reader :size
end

# after
require 'puppet/pops/types/puppet_object'
class PuppetX::Mymod::Widget
  include Puppet::Pops::Types::PuppetObject
  attr_reader :size
end
Defensive patterns

Strategy: type-guard

Validate before calling

# Ruby — verify the contract after loading the mapped class
klass = Puppet::Pops::Types::ClassLoader.provide(class_name)
unless klass.nil? || (klass < Puppet::Pops::Types::PuppetObject || klass.respond_to?(:ecore))
  fail("#{class_name} must include PuppetObject or be an RGen (ecore) class")
end

Type guard

def puppet_object_class?(klass)
  klass < Puppet::Pops::Types::PuppetObject || klass.respond_to?(:ecore)
end

Try / catch

begin
  obj_type.implementation_class
rescue Puppet::Error => e
  raise TypeError, "#{e.message} — include Puppet::Pops::Types::PuppetObject in the mapped class"
end

Prevention

When it happens

Trigger: The registry mapping resolves to an existing Ruby class that is not a Puppet object implementation — e.g. a name collision where the mapped name resolves to a helper/stdlib class (::Set, ::Logger, a module of your own), or a hand-written implementation class created without including PuppetObject.

Common situations: Mapping a data type to an arbitrary domain class expecting Puppet to adapt it automatically; constant resolution picking up an unexpected toplevel constant of the same name; upgrading code where the implementation was replaced by a plain class.

Related errors


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