{"record":{"id":"8ee2ae8bef0c88d9","repo":"puppetlabs/puppet","slug":"invalid-module-name-name-module-names-must-m","errorCode":null,"errorMessage":"Invalid module name '%{name}'; module names must match either:\n        An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or-\n        A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/","messagePattern":"Invalid module name '%(.+?)'; module names must match either:\n        An installed module name \\(ex\\. modulename\\) matching the expression /\\^\\[a-z\\]\\[a-z0-9_\\]\\*\\$/ -or-\n        A namespaced module name \\(ex\\. author-modulename\\) matching the expression /\\^\\[a-zA-Z0-9\\]\\+\\[-\\]\\[a-z\\]\\[a-z0-9_\\]\\*\\$/","errorType":"exception","errorClass":"InvalidName","httpStatus":null,"severity":"error","filePath":"lib/puppet/module.rb","lineNumber":480,"sourceCode":"      extended = File.extname(pattern).empty? ? \"#{pattern}.pp\" : pattern\n      relative_pattern = Puppet::FileSystem::PathPattern.relative(extended)\n    rescue Puppet::FileSystem::PathPattern::InvalidPattern => error\n      raise Puppet::Module::InvalidFilePattern.new(\n        \"The pattern \\\"#{pattern}\\\" to find manifests in the module \\\"#{name}\\\" \" \\\n        \"is invalid and potentially unsafe.\", error\n      )\n    end\n\n    relative_pattern.prefix_with(@absolute_path_to_manifests)\n  end\n\n  def subpath(type)\n    File.join(path, type)\n  end\n\n  def assert_validity\n    if !Puppet::Module.is_module_directory_name?(@name) && !Puppet::Module.is_module_namespaced_name?(@name)\n      raise InvalidName, _(<<-ERROR_STRING).chomp % { name: @name }\n        Invalid module name '%{name}'; module names must match either:\n        An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or-\n        A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/\n      ERROR_STRING\n    end\n  end\nend\n","sourceCodeStart":462,"sourceCodeEnd":488,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module.rb#L462-L488","documentation":"Raised by Puppet::Module#assert_validity when a module's directory name fails both the installed-module pattern /^[a-z][a-z0-9_]*$/ and the namespaced pattern /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/. Puppet derives a module's name from its directory, so an illegal directory name makes the module unloadable because its class/defined-type names (module::class) would not resolve. This check runs whenever Puppet constructs a Puppet::Module object from a directory on the modulepath.","triggerScenarios":"A directory under environment.modulespath or basemodulepath whose name starts with an uppercase letter, digit, or dash (e.g. 'MyModule', '1module', 'mod-name_2x', 'mod--name'), or a namespaced name whose right side violates the lowercase rule (e.g. 'author-Mod'). Constructing Puppet::Module.new for that path (which module loading does at environment compilation time) raises Puppet::Module::InvalidName.","commonSituations":"Cloning a git repo into site-modules with a CamelCase repo name; extracting a Forge tarball that renames to a capitalized folder; hand-created directories with dashes in the shortname or hyphen-separated names that do not follow author-modulename form; leftover temp directories matching /^[.#~]/ artifacts.","solutions":["Rename the module directory to lowercase letters/digits/underscores, e.g. 'MyModule' -> 'mymodule', or 'author-modulename' form for namespaced names.","If the directory is not a module (build output, editor droppings), delete or move it out of the modulepath.","Run `puppet module list` or `puppet agent --test --noop` after renaming to confirm the module loads and its classes resolve.","Update any site.pp / Profile references that used the old class name derived from the old directory name."],"exampleFix":"# before: site-modules/MyModule/manifests/init.pp\nclass MyModule { }\n\n# after: site-modules/mymodule/manifests/init.pp\nclass mymodule { }","handlingStrategy":"validation","validationCode":"def valid_module_dir_name?(name)\n  name =~ /\\A[a-z][a-z0-9_]*\\z/ || name =~ /\\A[a-zA-Z0-9]+-[a-z][a-z0-9_]*\\z/\nend\n\n# before adding/renaming a directory on the modulepath:\nraise \"bad module dir name: #{dir}\" unless valid_module_dir_name?(File.basename(dir))","typeGuard":"def module_name?(str)\n  str.is_a?(String) && (str.match?(\\A[a-z][a-z0-9_]*\\z) || str.match?(\\A[a-zA-Z0-9]+-[a-z][a-z0-9_]*\\z))\nend","tryCatchPattern":"begin\n  mod = Puppet::Module.new(name, path, environment)\n  mod.validate\nrescue Puppet::Module::InvalidName => e\n  logger.warn \"skipping invalid module directory #{path}: #{e.message}\"\n  next\nend","preventionTips":["Enforce lowercase snake_case in CI lint rules for module directory names (metadata-lint / puppet-lint plugins).","Name git repos for modules in the final lowercase form so checkouts never need renaming.","When enumerating modules, skip directories failing the name regex instead of aborting the whole environment load."],"tags":["puppet","module","name-validation","modulepath"],"backgroundTag":"invalid-module-name","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}