{"record":{"id":"76c51e1e770a30e8","repo":"puppetlabs/puppet","slug":"the-code-loaded-from-source-ref-produced-type-w","errorCode":null,"errorMessage":"The code loaded from %{source_ref} produced type with the wrong name, expected '%{name}', actual '%{actual_name}'","messagePattern":"The code loaded from %(.+?) produced type with the wrong name, expected '%(.+?)', actual '%(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/loader/type_definition_instantiator.rb","lineNumber":33,"sourceCode":"    case model.definitions.size\n    when 0\n      raise ArgumentError, _(\"The code loaded from %{source_ref} does not define the type '%{name}' - it is empty.\") % { source_ref: source_ref, name: name }\n    when 1\n      # ok\n    else\n      raise ArgumentError,\n            _(\"The code loaded from %{source_ref} must contain only the type '%{name}' - it has additional definitions.\") % { source_ref: source_ref, name: name }\n    end\n    type_definition = model.definitions[0]\n\n    unless type_definition.is_a?(Model::TypeAlias) || type_definition.is_a?(Model::TypeDefinition)\n      raise ArgumentError,\n            _(\"The code loaded from %{source_ref} does not define the type '%{name}' - no type alias or type definition found.\") % { source_ref: source_ref, name: name }\n    end\n\n    actual_name = type_definition.name\n    unless name == actual_name.downcase\n      raise ArgumentError,\n            _(\"The code loaded from %{source_ref} produced type with the wrong name, expected '%{name}', actual '%{actual_name}'\") % { source_ref: source_ref, name: name, actual_name: actual_name }\n    end\n\n    unless model.body == type_definition\n      raise ArgumentError,\n            _(\"The code loaded from %{source_ref} contains additional logic - can only contain the type '%{name}'\") % { source_ref: source_ref, name: name }\n    end\n\n    # Adapt the type definition with loader - this is used from logic contained in its body to find the\n    # loader to use when resolving contained aliases API. Such logic have a hard time finding the closure (where\n    # the loader is known - hence this mechanism\n    private_loader = loader.private_loader\n    Adapters::LoaderAdapter.adapt(type_definition).loader_name = private_loader.loader_name\n    create_runtime_type(type_definition)\n  end\n\n  def self.create_from_model(type_definition, loader)\n    typed_name = TypedName.new(:type, type_definition.name)","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/loader/type_definition_instantiator.rb#L15-L51","documentation":"TypeDefinitionInstantiator.create compares the type name the loader expects (typed_name.name, already lowercase, e.g. 'mymodule::mytype') against type_definition.name.downcase. If the defined name differs — even by one segment — this ArgumentError reports both names. Puppet type files must define exactly the type they are named after, case-insensitively, so types/MyType.pp must define mymodule::MyType (any casing), not some other name.","triggerScenarios":"types/mytype.pp that declares `type mymodule::othertype = String`; copy-pasting a type file and editing the body but not the name; renaming a type in code without renaming/rewriting the file; module rename leaving old type names inside files.","commonSituations":"Module renamed but types/ contents not updated; refactoring aliases and forgetting one file; casing is fine (downcase comparison) but segment spelling is not.","solutions":["Make the name inside the file match the file path: file types/<name>.pp must declare `type <module>::<name>`.","If you renamed the type, rename the file to match the new name and update references.","Delete duplicated files that declare a type belonging to another filename."],"exampleFix":"// before: modules/mymodule/types/mytype.pp\ntype mymodule::othertype = String\n\n// after: modules/mymodule/types/mytype.pp\ntype mymodule::mytype = String","handlingStrategy":"validation","validationCode":"# CI check: declared type name matches file path\nrequire 'puppet'\nrequire 'puppet/pops'\n\nDir['modules/*/types/**/*.pp'].each do |f|\n  module_name = f.split('/')[1]\n  expected = File.basename(f, '.pp')\n  model = Puppet::Pops::Parser::EvaluatingParser.new.parse_string(File.read(f), f)\n  actual = model.definitions[0]&.name.to_s\n  ok = actual.downcase == \"#{module_name}::#{expected}\".downcase\n  abort \"#{f}: declares #{actual}, expected #{module_name}::#{expected}\" unless ok\nend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive the file path from the type name mechanically when creating new types (script it).","After renaming a type, grep for the old name and rename the file in the same commit.","CI check comparing declared name to file path catches this pre-deploy."],"tags":["puppet","type-alias","name-mismatch","autoload","argumenterror"],"backgroundTag":"puppet-type-name-mismatch","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}