{"record":{"id":"6d367a0a9e5aab23","repo":"puppetlabs/puppet","slug":"a-data-type-can-only-have-one-interface","errorCode":null,"errorMessage":"a data type can only have one interface","messagePattern":"a data type can only have one interface","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/datatypes.rb","lineNumber":197,"sourceCode":"      end\n      created_type\n    end\n\n    def has_implementation?\n      !(@implementation_class.nil? && @implementation.nil?)\n    end\n  end\n\n  # The TypeBuilderAPI class exposes only those methods that the builder API provides\n  # @api public\n  class TypeBuilderAPI\n    # @api private\n    def initialize(type_builder)\n      @type_builder = type_builder\n    end\n\n    def interface(type_string)\n      raise ArgumentError, _('a data type can only have one interface') unless @type_builder.interface.nil?\n\n      @type_builder.interface = type_string\n    end\n\n    def implementation(&block)\n      raise ArgumentError, _('a data type can only have one implementation') if @type_builder.has_implementation?\n\n      @type_builder.implementation = block\n    end\n\n    def implementation_class(ruby_class)\n      raise ArgumentError, _('a data type can only have one implementation') if @type_builder.has_implementation?\n\n      @type_builder.implementation_class = ruby_class\n    end\n\n    def load_file(file_name)\n      Puppet::Util::Autoload.load_file(file_name, Puppet.lookup(:current_environment))","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/datatypes.rb#L179-L215","documentation":"TypeBuilderAPI#interface raises ArgumentError when an interface was already assigned — a data type's interface may be declared exactly once per create_type block. The guard is `unless @type_builder.interface.nil?`.","triggerScenarios":"Two `interface '...'` calls inside one Puppet::DataTypes.create_type block — typically a copied example followed by the author's own declaration, or code generators concatenating fragments.","commonSituations":"Copy-paste editing of data type definitions; template systems that append a default interface after a user-supplied one.","solutions":["Delete all but one interface declaration in the block","If you meant to merge two definitions, combine their attribute hashes into a single interface string","For generated code, emit the interface call once and assert on it (see validation)"],"exampleFix":"# before\nPuppet::DataTypes.create_type('T') do\n  interface 'attributes => { a => String }'\n  interface 'attributes => { b => Integer }'\nend\n# after\nPuppet::DataTypes.create_type('T') do\n  interface 'attributes => { a => String, b => Integer }'\nend","handlingStrategy":"validation","validationCode":"# authoring-time lint: one interface call per type file\nsrc = File.read(path)\ncount = src.scan(/^\\s*interface(\\s|<<-)/).size\nraise \"#{path}: expected exactly 1 interface call, found #{count}\" unless count == 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep interface declarations at the top of the block, one per type","Add a unit test counting interface calls in generated data type files"],"tags":["puppet","data-types","pcore","duplicate-definition"],"backgroundTag":"duplicate-definition","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}