puppetlabs/puppet · error · Puppet::ModuleTool::Errors::InvalidModuleNameError

Could not %{action} '%{module_name}', did you mean '%{sugges

Error message

Could not %{action} '%{module_name}', did you mean '%{suggestion}'?

What it means

Raised by Puppet::ModuleTool::Installer#run (wrapped as InvalidModuleNameError in lib/puppet/module_tool/errors/shared.rb:131) when `puppet module install` is given a Forge module name that contains no hyphen and the argument is not a path to a local tarball. Forge module names must be namespaced as `<owner>-<module>` (e.g. puppetlabs-apache), because the hyphen separates the Forge username from the module name. The error includes a suggestion built by prefixing the short name with the most common owner ("puppetlabs-<name>").

Source

Thrown at lib/puppet/module_tool/applications/installer.rb:64

            SemanticPuppet::Dependency.add_source(installed_modules_source)
            SemanticPuppet::Dependency.add_source(module_repository)
          end

        else
          SemanticPuppet::Dependency.add_source(installed_modules_source) unless forced?
          SemanticPuppet::Dependency.add_source(module_repository)
        end
      end

      def run
        name = @name.tr('/', '-')
        version = options[:version] || '>= 0.0.0'

        results = { :action => :install, :module_name => name, :module_version => version }

        begin
          if !@local_tarball && name !~ /-/
            raise InvalidModuleNameError.new(module_name: @name, suggestion: "puppetlabs-#{@name}", action: :install)
          end

          installed_module = installed_modules[name]
          if installed_module
            unless forced?
              if Puppet::Module.parse_range(version).include? installed_module.version
                results[:result] = :noop
                results[:version] = installed_module.version
                return results
              else
                changes = begin
                  Checksummer.run(installed_modules[name].mod.path)
                rescue
                  []
                end
                raise AlreadyInstalledError,
                      :module_name => name,
                      :installed_version => installed_modules[name].version,

View on GitHub (pinned to e227c27540)

Solutions

  1. Use the fully-qualified Forge name shown in the suggestion: `puppet module install puppetlabs-apache`
  2. If you meant a specific owner, prefix that owner: `puppet module install <owner>-<name>` (e.g. puppet-nginx)
  3. If installing a local package, pass the tarball path instead: `puppet module install ./pkg/apache-9.0.0.tar.gz`
  4. In code, validate the name with /\A[a-z0-9]+-[a-z0-9_]+\z/ before calling the installer

Example fix

# before
puppet module install apache
# after
puppet module install puppetlabs-apache
Defensive patterns

Strategy: validation

Validate before calling

# Ruby: validate a Forge module name before invoking the installer
name = 'apache'
unless name.match?(%r{\A[a-z0-9][a-z0-9_-]*/[a-z0-9_]+\z}) || name.match?(%r{\A[a-z0-9]+-[a-z0-9_]+\z}) || File.exist?(name)
  raise ArgumentError, "#{name} lacks the required owner- prefix; did you mean puppetlabs-#{name}?"
end

Try / catch

begin
  Puppet::ModuleTool::Applications::Installer.run(name, options)
rescue Puppet::ModuleTool::Errors::InvalidModuleNameError => e
  # e.multiline prints the suggested fully-qualified command
  puts e.multiline
  raise
end

Prevention

When it happens

Trigger: Running `puppet module install apache` (single word, no slash-to-hyphen translation produces a hyphen-less name). Specifically: `!@local_tarball && name !~ /-/` in installer.rb — i.e. the argument is not an existing tarball file path AND `name.tr('/', '-')` still contains no '-'. Also triggered by the Puppet code API Puppet::ModuleTool::Applications::Installer.run('apache', ...) with the same shape.

Common situations: New users installing from the Forge by short name (`puppet module install stdlib` instead of `puppetlabs-stdlib`); shell scripts that pass $MODULE without the owner prefix; typos where the dash is omitted; automation that fetches module names from a list that stores only the short name.

Related errors


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