{"record":{"id":"e1f4538d584897c3","repo":"puppetlabs/puppet","slug":"could-not-action-module-name-module-appea-e1f453","errorCode":null,"errorMessage":"Could not %{action} '%{module_name}'; module appears in multiple places in the module path","messagePattern":"Could not %(.+?) '%(.+?)'; module appears in multiple places in the module path","errorType":"exception","errorClass":"Puppet::ModuleTool::Errors::MultipleInstalledError","httpStatus":null,"severity":"error","filePath":"lib/puppet/module_tool/applications/upgrader.rb","lineNumber":50,"sourceCode":"\n        name = @name.tr('/', '-')\n        version = options[:version] || '>= 0.0.0'\n\n        results = {\n          :action => :upgrade,\n          :requested_version => options[:version] || :latest,\n        }\n\n        begin\n          all_modules = @environment.modules_by_path.values.flatten\n          matching_modules = all_modules.select do |x|\n            x.forge_name && x.forge_name.tr('/', '-') == name\n          end\n\n          if matching_modules.empty?\n            raise NotInstalledError, results.merge(:module_name => name)\n          elsif matching_modules.length > 1\n            raise MultipleInstalledError, results.merge(:module_name => name, :installed_modules => matching_modules)\n          end\n\n          installed_release = installed_modules[name]\n\n          # `priority` is an attribute of a `SemanticPuppet::Dependency::Source`,\n          # which is delegated through `ModuleRelease` instances for the sake of\n          # comparison (sorting). By default, the `InstalledModules` source has\n          # a priority of 10 (making it the most preferable source, so that\n          # already installed versions of modules are selected in preference to\n          # modules from e.g. the Forge). Since we are specifically looking to\n          # upgrade this module, we don't want the installed version of this\n          # module to be chosen in preference to those with higher versions.\n          #\n          # This implementation is suboptimal, and since we can expect this sort\n          # of behavior to be reasonably common in Semantic, we should probably\n          # see about implementing a `ModuleRelease#override_priority` method\n          # (or something similar).\n          def installed_release.priority","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module_tool/applications/upgrader.rb#L32-L68","documentation":"Raised by the Upgrader as Puppet::ModuleTool::Errors::MultipleInstalledError when more than one installed module matches the requested forge name. The candidate search covers every directory in the modulepath, so two copies of the same module (e.g. one in the environment's modulepath and one in basemodulepath) make the upgrade target ambiguous and Puppet refuses to pick one.","triggerScenarios":"Running `puppet module upgrade <author-module>` while a module with the same forge_name exists in two or more modulepath directories (matching_modules.length > 1), e.g. environment 'modules/' plus '/etc/puppetlabs/code/environments/production/modules' and a site-wide path.","commonSituations":"Module installed both per-environment and globally; a directory copied manually next to a puppet-installed copy; basemodulepath defaults pulling in an extra location; leftover copies after a migration of code to a new environment path.","solutions":["Run `puppet module list --environment <env>` (and check `puppet config print modulepath basemodulepath`) to locate every copy","Remove the stale copy: `puppet module uninstall <name> --environment <env>` or delete the redundant directory manually","Keep exactly one canonical location per environment and let Puppetfile/r10k manage it","Retry `puppet module upgrade <name>` once only one match remains"],"exampleFix":"# before\n$ puppet module upgrade puppetlabs-stdlib\n# Error: ... module appears in multiple places in the module path\n\n# after\n$ puppet module list --tree   # shows both copies\n$ rm -rf /etc/puppetlabs/code/modules/stdlib   # remove global copy\n$ puppet module upgrade puppetlabs-stdlib","handlingStrategy":"validation","validationCode":"matches = env.modules_by_path.values.flatten\n  .select { |m| m.forge_name && m.forge_name.tr('/', '-') == name }\nif matches.length > 1\n  abort \"multiple copies: #{matches.map(&:modulepath).join(', ')} — remove all but one\"\nend","typeGuard":null,"tryCatchPattern":"result = Puppet::ModuleTool::Applications::Upgrader.new(name, options).run\nif result[:error] && result[:error][:oneline] =~ /multiple places/\n  matches.each { |m| FileUtils.rm_rf(m.path) }  # or keep the canonical one\n  retry\nend","preventionTips":["Keep one module location per environment and let r10k own it; avoid mixing basemodulepath installs with environment installs","After environment migrations, sweep for leftover module directories with the same short name","Audit modulepath (`puppet config print modulepath basemodulepath`) in CI so extra paths fail loudly"],"tags":["puppet","module-tool","upgrade","duplicate","modulepath"],"backgroundTag":"duplicate-module-installation","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}