puppetlabs/puppet · error · Serialization::SerializationError

Initializer for class #{impl_class.name} does not match the

Error message

Initializer for class #{impl_class.name} does not match the attributes of #{name}

What it means

When Puppet instantiates or pcore-deserializes an Object type with a Ruby implementation class, parameter_info compares the parameters of the impl class's initialize method against the type's declared attributes. Serialization::SerializationError is raised when initialize accepts fewer parameters than there are attributes, or has more required parameters than attributes - meaning instances could not be constructed faithfully from their attribute values.

Source

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

    param_types = non_opt_types + opt_types
    param_count = param_names.size

    init = impl_class.respond_to?(:from_asserted_args) ? impl_class.method(:from_asserted_args) : impl_class.instance_method(:initialize)
    init_non_opt_count = 0
    init_param_names = init.parameters.map do |p|
      init_non_opt_count += 1 if :req == p[0]
      n = p[1].to_s
      r = RubyGenerator.unprotect_reserved_name(n)
      unless r.equal?(n)
        # assert that the protected name wasn't a real name (names can start with underscore)
        n = r unless param_names.index(r).nil?
      end
      n
    end

    if init_param_names != param_names
      if init_param_names.size < param_count || init_non_opt_count > param_count
        raise Serialization::SerializationError, "Initializer for class #{impl_class.name} does not match the attributes of #{name}"
      end

      init_param_names = init_param_names[0, param_count] if init_param_names.size > param_count
      unless init_param_names == param_names
        # Reorder needed to match initialize method arguments
        new_param_types = []
        init_param_names.each do |ip|
          index = param_names.index(ip)
          if index.nil?
            raise Serialization::SerializationError,
                  "Initializer for class #{impl_class.name} parameter '#{ip}' does not match any of the attributes of type #{name}"
          end
          new_param_types << param_types[index]
        end
        param_names = init_param_names
        param_types = new_param_types
      end
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Align the implementation class's initialize parameter list with the type's attributes: same names, and every attribute covered
  2. If initialize must accept extra arguments, make them optional (default values); required params may never exceed the attribute count
  3. Re-check after every change to the interface's attributes block - names must match exactly (a leading underscore is treated as name protection, not a distinct name)

Example fix

# before
Puppet::DataTypes.create_type('MyApp::Point') do
  interface <<-PUPPET
    attributes => { x => Integer, y => Integer, z => Integer }
  PUPPET
  implementation_class Class.new do
    def initialize(x, y)      # z is not covered
      @x, @y = x, y
    end
  end
end

# after
  implementation_class Class.new do
    def initialize(x, y, z)   # covers all three attributes
      @x, @y, @z = x, y, z
    end
  end
Defensive patterns

Strategy: validation

Validate before calling

# before creating instances, compare initialize params with the type's attributes
params = impl_class.instance_method(:initialize).parameters
count = type.attributes(true).size
required = params.count { |kind, _| kind == :req }
names = params.map { |_, n| n.to_s.sub(/\A_/, '') }
abort 'initializer too small or too strict' if names.size < count || required > count
abort 'unknown initializer params: ' + (names - type.attributes(true).keys).inspect unless (names - type.attributes(true).keys).empty?

Try / catch

begin
  type.create(*args)
rescue Puppet::Pops::Serialization::SerializationError => e
  raise unless e.message =~ /Initializer for class/
  # re-raise with context: which type and which implementation class diverged
  raise "#{type.name}: implementation class out of sync with attributes: #{e.message}"
end

Prevention

When it happens

Trigger: Creating an instance (or deserializing one) of a type whose implementation class defines initialize(x, y) while the interface declares three attributes (x, y, z), or initialize(a, b, c) with all three required while the type only declares two attributes. The check runs lazily, typically on first new() call or during pcore serialization.

Common situations: An attribute was added to the interface string but the Ruby implementation_class initialize was never updated; attributes were renamed or reordered without touching the implementation; copying an implementation class from a similar type with a different attribute set.

Related errors


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