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

Could not %{action} '%{module_name}' (%{version}); no versio

Error message

Could not %{action} '%{module_name}' (%{version}); no version satisfies all dependencies

What it means

Installer raises Puppet::ModuleTool::NoVersionsSatisfyError when SemanticPuppet::Dependency.resolve raises UnsatisfiableGraph: there are releases for the module, but no combination of versions of it and its dependencies can satisfy every constraint (the module's own --version range plus version_requirement ranges of dependencies and already-installed modules). It captures the unsatisfied module name, the conflicting constraints, and the currently installed version when available.

Source

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

                dep_constraints = graph.dependencies[name].max.constraints

                if dep_constraints.key?(e.unsatisfied)
                  unsatisfied_range = dep_constraints[e.unsatisfied].first[1]
                  constraints[e.unsatisfied] = unsatisfied_range
                end
              end

              installed_module = @environment.module_by_forge_name(e.unsatisfied.tr('-', '/'))
              current_version = installed_module.version if installed_module

              unsatisfied = {
                :name => e.unsatisfied,
                :constraints => constraints,
                :current_version => current_version
              } if constraints.any?
            end

            raise NoVersionsSatisfyError, results.merge(
              :requested_name => name,
              :requested_version => options[:version] || graph.dependencies[name].max.version.to_s,
              :unsatisfied => unsatisfied
            )
          end

          unless forced?
            # Check for module name conflicts.
            releases.each do |rel|
              installed_module = installed_modules_source.by_name[rel.name.split('-').last]
              next unless installed_module
              next if installed_module.has_metadata? && installed_module.forge_name.tr('/', '-') == rel.name

              if rel.name != name
                dependency = {
                  :name => rel.name,
                  :version => rel.version
                }

View on GitHub (pinned to e227c27540)

Solutions

  1. Loosen or remove the --version pin and let the resolver choose a compatible set.
  2. Read the constraints in the error to find which module's range conflicts, then upgrade/downgrade that module explicitly to a version satisfying all ranges.
  3. Uninstall or upgrade the already-installed module that contributes the blocking constraint.
  4. As a last resort use --force with --ignore-dependencies (or fix the dependency's metadata) knowing dependency correctness is no longer guaranteed.

Example fix

# before
puppet module install puppetlabs-apache --version '>= 1.0.0 < 2.0.0'
# dependency needs concat >= 2.0 but pinned concat 1.x installed

# after
puppet module upgrade puppetlabs-concat --version '>= 2.0.0' && \
  puppet module install puppetlabs-apache --version '>= 1.0.0 < 2.0.0'
Defensive patterns

Strategy: try-catch

Try / catch

begin
  Puppet::ModuleTool::Applications::Installer.new(name, options).run
rescue Puppet::ModuleTool::NoVersionsSatisfyError => e
  # e.multiline_options[:unsatisfied] names the blocking module + constraints
  adjust_pin_and_retry(e)
end

Prevention

When it happens

Trigger: Installing with `--version '< 3.0.0'` while the module's dependencies require a newer version of another module than allowed; a dependency pinned by an already-installed module blocks the resolution; a dependency's version_requirement references a version range no published release of the dependency matches (common with legacy '>= 1.0.0' style ranges vs unavailable majors).

Common situations: Pinning old module versions in Puppetfiles while transitive deps moved on; Forge modules whose dependencies were yanked; long-lived control repos after dependency majors EOL; combining --version with existing installed sets that lock ranges.

Related errors


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