{"record":{"id":"dd4e6d1c17fafc1c","repo":"puppetlabs/puppet","slug":"attempt-to-redefine-implementation-class-for-lab","errorCode":null,"errorMessage":"attempt to redefine implementation class for #{label}","messagePattern":"attempt to redefine implementation class for #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_object_type.rb","lineNumber":574,"sourceCode":"        # Use generator to create a default implementation\n        @implementation_class = RubyGenerator.new.create_class(self)\n        @implementation_class.class_eval(&@implementation_override) if instance_variable_defined?(:@implementation_override)\n      else\n        # Can the mapping be loaded?\n        @implementation_class = ClassLoader.provide(class_name)\n\n        raise Puppet::Error, \"Unable to load class #{class_name}\" if @implementation_class.nil?\n        unless @implementation_class < PuppetObject || @implementation_class.respond_to?(:ecore)\n          raise Puppet::Error, \"Unable to create an instance of #{name}. #{class_name} does not include module #{PuppetObject.name}\"\n        end\n      end\n    end\n    @implementation_class\n  end\n\n  # @api private\n  def implementation_class=(cls)\n    raise ArgumentError, \"attempt to redefine implementation class for #{label}\" unless @implementation_class.nil?\n\n    @implementation_class = cls\n  end\n\n  # The block passed to this method will be passed in a call to `#class_eval` on the dynamically generated\n  # class for this data type. It's indended use is to complement or redefine the generated methods and\n  # attribute readers.\n  #\n  # The method is normally called with the block passed to `#implementation` when a data type is defined using\n  # {Puppet::DataTypes::create_type}.\n  #\n  # @api private\n  def implementation_override=(block)\n    if !@implementation_class.nil? || instance_variable_defined?(:@implementation_override)\n      raise ArgumentError, \"attempt to redefine implementation override for #{label}\"\n    end\n\n    @implementation_override = block","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_object_type.rb#L556-L592","documentation":"PObjectType#implementation_class= may be assigned exactly once; a second assignment raises ArgumentError with the type's label. The one-shot setter prevents silently swapping the Ruby class behind a live data type after instances or generated methods already exist.","triggerScenarios":"Ruby code calling type.implementation_class = cls when an implementation is already set — most commonly Puppet::DataTypes.create_type executed twice for the same type name in one process (two modules declaring the same data type, or test suites that load type definitions repeatedly), or custom registration code running on every request.","commonSituations":"Duplicate data type definitions with the same name across modules; rspec/task runs that re-evaluate type files without process isolation; frameworks that re-register types on reload without tracking what was already loaded.","solutions":["Define each data type name exactly once across all loaded modules; rename colliding types.","Guard the assignment: `type.implementation_class = cls if type.implementation_class.nil?` in code that may run twice.","In long-lived custom hosts, memoize type registration so files are processed once per process."],"exampleFix":"# before\ntype.implementation_class = cls   # raises if already assigned\n\n# after\ntype.implementation_class = cls if type.implementation_class.nil?","handlingStrategy":"validation","validationCode":"# Ruby — make registration idempotent\ntype.implementation_class = cls if type.implementation_class.nil?","typeGuard":"def implementation_assignable?(type)\n  type.implementation_class.nil?\nend","tryCatchPattern":"begin\n  type.implementation_class = cls\nrescue ArgumentError => e\n  raise unless type.implementation_class == cls # tolerate benign re-registration of the same class\nend","preventionTips":["Give every data type a unique name across all modules in the environment.","In tests/long-lived processes, load type definition files once and memoize; never re-run create_type per request."],"tags":["puppet","object-type","implementation-class","duplicate-registration","ruby-api"],"backgroundTag":"duplicate-type-registration","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}