puppetlabs/puppet · error · ArgumentError
a data type can only have one implementation
Error message
a data type can only have one implementation
What it means
TypeBuilderAPI#implementation raises ArgumentError when has_implementation? is true — i.e. the type already has an implementation from an earlier `implementation { }` block or from `implementation_class`. A Puppet data type can carry exactly one implementation.
Source
Thrown at lib/puppet/datatypes.rb:203
end
end
# The TypeBuilderAPI class exposes only those methods that the builder API provides
# @api public
class TypeBuilderAPI
# @api private
def initialize(type_builder)
@type_builder = type_builder
end
def interface(type_string)
raise ArgumentError, _('a data type can only have one interface') unless @type_builder.interface.nil?
@type_builder.interface = type_string
end
def implementation(&block)
raise ArgumentError, _('a data type can only have one implementation') if @type_builder.has_implementation?
@type_builder.implementation = block
end
def implementation_class(ruby_class)
raise ArgumentError, _('a data type can only have one implementation') if @type_builder.has_implementation?
@type_builder.implementation_class = ruby_class
end
def load_file(file_name)
Puppet::Util::Autoload.load_file(file_name, Puppet.lookup(:current_environment))
end
end
end
View on GitHub (pinned to e227c27540)
Solutions
- Keep exactly one implementation source: either one implementation block or one implementation_class, not both
- To share behavior, put helpers in a Ruby module and include it inside the single implementation block
- Merge the bodies of duplicate implementation blocks into one
Example fix
# before
Puppet::DataTypes.create_type('T') do
interface 'attributes => {}'
implementation_class AcmeImpl
implementation { def extra; 1; end }
end
# after
Puppet::DataTypes.create_type('T') do
interface 'attributes => {}'
implementation_class AcmeImpl # sole implementation
end Defensive patterns
Strategy: validation
Validate before calling
src = File.read(path)
impl_calls = src.scan(/^\s*implementation(_class)?(\s|\{|\()/).size
raise "#{path}: expected exactly 1 implementation, found #{impl_calls}" unless impl_calls == 1 Prevention
- Choose one style per type: implementation block OR implementation_class, never both
- Share behavior via modules included inside the single implementation block
When it happens
Trigger: Two `implementation { ... }` blocks in one create_type block; `implementation_class Foo` followed by `implementation { ... }` (or the reverse order).
Common situations: Copying behavior from another type by pasting its implementation block alongside an existing implementation_class; merging two data types by hand.
Related errors
- a data type can only have one interface
- Data Type Load Error for type '%{type_name}': %{message}
- a data type must have an interface
- attempt to redefine implementation override for #{label}
- title patterns that use procs are not supported.
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/4ef574a67b14f6e3.
Report an issue: GitHub.