puppetlabs/puppet · error · InvalidName

Invalid module name '%{name}'; module names must match eithe

Error message

Invalid module name '%{name}'; module names must match either:
        An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or-
        A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/

What it means

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.

Source

Thrown at lib/puppet/module.rb:480

      extended = File.extname(pattern).empty? ? "#{pattern}.pp" : pattern
      relative_pattern = Puppet::FileSystem::PathPattern.relative(extended)
    rescue Puppet::FileSystem::PathPattern::InvalidPattern => error
      raise Puppet::Module::InvalidFilePattern.new(
        "The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " \
        "is invalid and potentially unsafe.", error
      )
    end

    relative_pattern.prefix_with(@absolute_path_to_manifests)
  end

  def subpath(type)
    File.join(path, type)
  end

  def assert_validity
    if !Puppet::Module.is_module_directory_name?(@name) && !Puppet::Module.is_module_namespaced_name?(@name)
      raise InvalidName, _(<<-ERROR_STRING).chomp % { name: @name }
        Invalid module name '%{name}'; module names must match either:
        An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or-
        A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
      ERROR_STRING
    end
  end
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Rename the module directory to lowercase letters/digits/underscores, e.g. 'MyModule' -> 'mymodule', or 'author-modulename' form for namespaced names.
  2. If the directory is not a module (build output, editor droppings), delete or move it out of the modulepath.
  3. Run `puppet module list` or `puppet agent --test --noop` after renaming to confirm the module loads and its classes resolve.
  4. Update any site.pp / Profile references that used the old class name derived from the old directory name.

Example fix

# before: site-modules/MyModule/manifests/init.pp
class MyModule { }

# after: site-modules/mymodule/manifests/init.pp
class mymodule { }
Defensive patterns

Strategy: validation

Validate before calling

def valid_module_dir_name?(name)
  name =~ /\A[a-z][a-z0-9_]*\z/ || name =~ /\A[a-zA-Z0-9]+-[a-z][a-z0-9_]*\z/
end

# before adding/renaming a directory on the modulepath:
raise "bad module dir name: #{dir}" unless valid_module_dir_name?(File.basename(dir))

Type guard

def module_name?(str)
  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))
end

Try / catch

begin
  mod = Puppet::Module.new(name, path, environment)
  mod.validate
rescue Puppet::Module::InvalidName => e
  logger.warn "skipping invalid module directory #{path}: #{e.message}"
  next
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/8ee2ae8bef0c88d9. Report an issue: GitHub.