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

After the resolver intersects every version range imposed on a dependency and selects candidate releases from the Forge, it prefers final releases over prereleases (semver.special == '') and falls back to prereleases only when no final release matches. If the filtering still yields zero releases (valid_versions.last is nil), NoVersionsSatisfyError aborts the operation: no published release of that dependency satisfies the combined constraints.

Source

Thrown at lib/puppet/module_tool/shared_behaviors.rb:132

        action = :upgrade
      elsif @installed[mod].empty?
        action = :install
      end

      if action == :upgrade
        @conditions.each { |_, conds| conds.delete_if { |c| c[:module] == mod } }
      end

      versions = @versions[mod.to_s].select { |h| range === h[:semver] }
      valid_versions = versions.select { |x| x[:semver].special == '' }
      valid_versions = versions if valid_versions.empty?

      version = valid_versions.last
      unless version
        req_module   = @module_name
        req_versions = @versions[@module_name.to_s].map { |v| v[:semver] }
        raise NoVersionsSatisfyError,
              :requested_name => req_module,
              :requested_version => @version || annotated_version(req_module, req_versions),
              :installed_version => @installed[@module_name].empty? ? nil : @installed[@module_name].first.version,
              :dependency_name => mod,
              :conditions => @conditions[mod],
              :action => @action
      end

      seen[mod] = version

      {
        :module => mod,
        :version => version,
        :action => action,
        :previous_version => @installed[mod].empty? ? nil : @installed[mod].first.version,
        :file => @urls["#{mod}@#{version[:vstring]}"],
        :path => if action == :install
                   @options[:target_dir]

View on GitHub (pinned to e227c27540)

Solutions

  1. Read dependency_name and the conditions in the error message, then widen that version_requirement in your metadata.json to include at least one published release.
  2. Install another release of the module you are requesting whose dependency set matches reality: puppet module install author/mod --version X.Y.Z.
  3. Upgrade or remove the other module imposing the conflicting half of the range (it shows up in the conditions list).
  4. Confirm on the Forge (forge.puppet.com / forgeapi.puppet.com) which releases of the dependency actually exist before tightening any range.

Example fix

# before (metadata.json) — intersection with the other dependent's 'stdlib < 9.0.0' is empty
{"dependencies": [{"name": "puppetlabs/stdlib", "version_requirement": ">= 9.5.0"}]}

# after — a range both dependents accept
{"dependencies": [{"name": "puppetlabs/stdlib", "version_requirement": ">= 8.0.0 < 10.0.0"}]}
Defensive patterns

Strategy: try-catch

Validate before calling

require 'semantic_puppet'
releases = forge_releases_for(dep_name) # e.g. ['1.0.0', '8.6.0', '9.4.0']
ranges = constraints_on(dep_name).map { |r| SemanticPuppet::VersionRange.parse(r) }
shared = ranges.inject(&:&)
ok = shared && releases.any? { |v| shared === SemanticPuppet::Version.parse(v) }
abort "no release of #{dep_name} satisfies #{ranges.map(&:to_s).join(' & ')}" unless ok

Try / catch

begin
  # puppet module install author/mod
rescue Puppet::ModuleTool::Errors::NoVersionsSatisfyError => e
  # e.message names the dependency and the unsatisfiable conditions
  warn e.message
  exit 1
end

Prevention

When it happens

Trigger: 'puppet module install' or 'puppet module upgrade' where @versions[mod].select { |h| range === h[:semver] } is empty: constraints intersect to something like '>= 3.2.0 < 3.2.0', or the only needed release was never published or was deleted from the Forge.

Common situations: Over-tight metadata.json ranges (typos like '>= 1.2.3 < 1.2.3'); two modules pinning disjoint ranges of a shared dependency (stdlib >= 9 vs < 9); depending on a yanked release; dependency renamed so its old name has no matching releases.

Related errors


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