{"record":{"id":"f7286f1a703a0116","repo":"puppetlabs/puppet","slug":"initializer-for-class-impl-class-name-does-not","errorCode":null,"errorMessage":"Initializer for class #{impl_class.name} does not match the attributes of #{name}","messagePattern":"Initializer for class #(.+?) does not match the attributes of #(.+?)","errorType":"exception","errorClass":"Serialization::SerializationError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_object_type.rb","lineNumber":648,"sourceCode":"    param_types = non_opt_types + opt_types\n    param_count = param_names.size\n\n    init = impl_class.respond_to?(:from_asserted_args) ? impl_class.method(:from_asserted_args) : impl_class.instance_method(:initialize)\n    init_non_opt_count = 0\n    init_param_names = init.parameters.map do |p|\n      init_non_opt_count += 1 if :req == p[0]\n      n = p[1].to_s\n      r = RubyGenerator.unprotect_reserved_name(n)\n      unless r.equal?(n)\n        # assert that the protected name wasn't a real name (names can start with underscore)\n        n = r unless param_names.index(r).nil?\n      end\n      n\n    end\n\n    if init_param_names != param_names\n      if init_param_names.size < param_count || init_non_opt_count > param_count\n        raise Serialization::SerializationError, \"Initializer for class #{impl_class.name} does not match the attributes of #{name}\"\n      end\n\n      init_param_names = init_param_names[0, param_count] if init_param_names.size > param_count\n      unless init_param_names == param_names\n        # Reorder needed to match initialize method arguments\n        new_param_types = []\n        init_param_names.each do |ip|\n          index = param_names.index(ip)\n          if index.nil?\n            raise Serialization::SerializationError,\n                  \"Initializer for class #{impl_class.name} parameter '#{ip}' does not match any of the attributes of type #{name}\"\n          end\n          new_param_types << param_types[index]\n        end\n        param_names = init_param_names\n        param_types = new_param_types\n      end\n    end","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_object_type.rb#L630-L666","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Align the implementation class's initialize parameter list with the type's attributes: same names, and every attribute covered","If initialize must accept extra arguments, make them optional (default values); required params may never exceed the attribute count","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)"],"exampleFix":"# before\nPuppet::DataTypes.create_type('MyApp::Point') do\n  interface <<-PUPPET\n    attributes => { x => Integer, y => Integer, z => Integer }\n  PUPPET\n  implementation_class Class.new do\n    def initialize(x, y)      # z is not covered\n      @x, @y = x, y\n    end\n  end\nend\n\n# after\n  implementation_class Class.new do\n    def initialize(x, y, z)   # covers all three attributes\n      @x, @y, @z = x, y, z\n    end\n  end","handlingStrategy":"validation","validationCode":"# before creating instances, compare initialize params with the type's attributes\nparams = impl_class.instance_method(:initialize).parameters\ncount = type.attributes(true).size\nrequired = params.count { |kind, _| kind == :req }\nnames = params.map { |_, n| n.to_s.sub(/\\A_/, '') }\nabort 'initializer too small or too strict' if names.size < count || required > count\nabort 'unknown initializer params: ' + (names - type.attributes(true).keys).inspect unless (names - type.attributes(true).keys).empty?","typeGuard":null,"tryCatchPattern":"begin\n  type.create(*args)\nrescue Puppet::Pops::Serialization::SerializationError => e\n  raise unless e.message =~ /Initializer for class/\n  # re-raise with context: which type and which implementation class diverged\n  raise \"#{type.name}: implementation class out of sync with attributes: #{e.message}\"\nend","preventionTips":["Treat the interface attributes block and the implementation initialize as one unit: change them in the same commit","Cover data type instantiation with a unit test so the check fires at test time, not during a production catalog compile","Prefer implementation blocks over custom initialize when possible; the generated initializer always matches"],"tags":["puppet","pcore","serialization","object-type","ruby"],"backgroundTag":"constructor-signature-mismatch","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}