puppetlabs/puppet · error · ArgumentError
attempt to redefine implementation override for #{label}
Error message
attempt to redefine implementation override for #{label} What it means
Puppet data types defined with Puppet::DataTypes.create_type may carry an implementation block that is later class_eval'd into the generated implementation class (set via implementation_override= in lib/puppet/datatypes.rb:178). The setter is one-shot: it raises ArgumentError if the PObjectType already has an implementation class or an override block. In practice this means the same data type was defined twice in one process, each time with an implementation block.
Source
Thrown at lib/puppet/pops/types/p_object_type.rb:589
# @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
# {Puppet::DataTypes::create_type}.
#
# @api private
def implementation_override=(block)
if !@implementation_class.nil? || instance_variable_defined?(:@implementation_override)
raise ArgumentError, "attempt to redefine implementation override for #{label}"
end
@implementation_override = block
end
def extract_init_hash(o)
return o._pcore_init_hash if o.respond_to?(:_pcore_init_hash)
result = {}
pic = parameter_info(o.class)
attrs = attributes(true)
pic[0].each do |name|
v = o.send(name)
result[name] = v unless attrs[name].default_value?(v)
end
result
end
View on GitHub (pinned to e227c27540)
Solutions
- Search the entire modulepath for files under lib/puppet/datatype/ and grep for create_type('<TypeName>') to find the duplicate definition; keep exactly one
- If two distinct types collided, rename one of them (names must be unique per name authority)
- Do not eval or require the datatype file manually; let Puppet's loader load it once, and never re-run create_type on reload - build a new PObjectType instead
- If re-registration is intentional in a dev loop, rescue ArgumentError and reuse the already-registered type
Example fix
# before: two files both declare the same type
# module_a/lib/puppet/datatype/myapp/thing.rb
# module_b/lib/puppet/datatype/myapp/thing.rb
Puppet::DataTypes.create_type('MyApp::Thing') do
interface <<-PUPPET
attributes => { value => String }
PUPPET
implementation { def extra; 42; end }
end
# after: delete one file so only a single definition remains
# (grep first: grep -r "create_type('MyApp::Thing')" <modulepath>) Defensive patterns
Strategy: try-catch
Validate before calling
# CI check: fail the build when two datatype files declare the same type
names = Dir['**/lib/puppet/datatype/**/*.rb'].flat_map do |f|
File.readlines(f).grep(/create_type\(['"]([^'"]+)['"]/) { Regexp.last_match(1) }.map { |n| [n, f] }
end
dupes = names.group_by(&:first).select { |_, v| v.size > 1 }
abort "duplicate data type definitions: #{dupes.inspect}" unless dupes.empty? Try / catch
begin
Puppet::DataTypes.create_type('MyApp::Thing') { ... }
rescue ArgumentError => e
raise unless e.message.include?('attempt to redefine implementation override')
# type already configured in this process; reuse it instead of redefining
Puppet::Pops::Types::TypeParser.singleton.parse('MyApp::Thing', loader)
end Prevention
- Keep data type names unique across all modules on the modulepath
- Never require or eval files under lib/puppet/datatype manually; let Puppet's loader do it exactly once
- Add a CI grep for duplicate create_type calls before deploying environments
- Avoid re-running create_type during hot reload; construct a fresh PObjectType instead
When it happens
Trigger: Calling Puppet::DataTypes.create_type('Some::Type') { ... implementation { ... } } twice in the same Ruby process: duplicate datatype files under two lib/puppet/datatype/ directories on the modulepath, the same file loaded by both environment setup and catalog compilation, or two modules declaring the same type name.
Common situations: Two modules shipping a data type with the same name; a data type defined at both environment level and module level; code reloaders (r10k, Code Manager, custom boot hooks) evaluating datatype files twice; agent and master running different code versions that both define a type.
Related errors
- a data type can only have one interface
- a data type can only have one implementation
- The code loaded from %{source_ref} does not seem to be a Pup
- The code loaded from %{source_ref} did not produce a data ty
- The code loaded from %{source_ref} produced mis-matched name
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/f4df144cefd30363.
Report an issue: GitHub.