puppetlabs/puppet · error · Puppet::Error
Could not list gems: %{detail}
Error message
Could not list gems: %{detail} What it means
gem.rb:126: the provider lists installed/available gems by shelling out (execute_gem_command, e.g. `gem list ...` or `gem list --remote --source ...`) and wrapping the run; when the gem command exits non-zero (Puppet::ExecutionFailure) it re-raises as Puppet::Error 'Could not list gems: %{detail}' with the command output attached. The listing is what powers instances, prefetch and query, so the error aborts gem package management for the run.
Source
Thrown at lib/puppet/provider/package/gem.rb:126
if options[:local]
command_options << "--local"
else
command_options << "--remote"
end
if options[:source]
command_options << "--source" << options[:source]
end
name = options[:justme]
if name
command_options << '\A' + name + '\z'
end
begin
list = execute_gem_command(options[:command], command_options).lines
.filter_map { |set| gemsplit(set) }
rescue Puppet::ExecutionFailure => detail
raise Puppet::Error, _("Could not list gems: %{detail}") % { detail: detail }, detail.backtrace
end
if options[:justme]
list.shift
else
list
end
end
def self.gemsplit(desc)
# `gem list` when output console has a line like:
# *** LOCAL GEMS ***
# but when it's not to the console that line
# and all blank lines are stripped
# so we don't need to check for them
if desc =~ /^(\S+)\s+\((.+)\)/
gem_name = Regexp.last_match(1)View on GitHub (pinned to e227c27540)
Solutions
- Reproduce as the puppet user with the same binary: `<gemcmd> list` — read %{detail} for the real stderr.
- Pin the correct ruby/gem explicitly: set `gemcmd`/`rubygem` command or use `provider => gem` with `command_options`/puppet settings so the intended gem binary is used.
- Fix environment issues: correct GEM_HOME/GEM_PATH, repair ownership of the gem home, or update CA certs / credentials for the remote source.
- If a remote source is flaky, consider mirroring gems internally instead of ensure => latest against the internet.
Example fix
# before
package { 'bundler': ensure => installed, provider => 'gem' } # picks wrong rvm ruby
# after
package { 'bundler': ensure => installed, provider => 'gem', install_options => ['--bindir', '/usr/local/bin'] }
# plus ensure puppet's gemcmd points at the system ruby (e.g. /usr/bin/gem), not an rvm shim Defensive patterns
Strategy: try-catch
Validate before calling
# verify the gem binary works as the puppet user
cmd = provider_gemcmd # e.g. /opt/ruby/bin/gem
out = `#{cmd} list 2>&1`
fail "gem broken: #{out}" unless $?.success? Try / catch
begin Puppet::Type.type(:package).provider(:gem).instances rescue Puppet::Error => e raise unless e.message =~ /Could not list gems/ # skip gem enumeration this run rather than failing the whole catalog Puppet.err(e.message); [] end
Prevention
- Pin gemcmd to an absolute, verified gem binary per node (no rvm/rbenv shims on the agent PATH).
- Check GEM_HOME/GEM_PATH ownership after any sudo gem usage.
- Mirror gem sources internally and monitor their TLS certs if you use ensure => latest.
When it happens
Trigger: Any gem package resource (or `puppet resource package provider=gem`) on a node where the configured gemcmd fails: bad gem executable path (wrong ruby via rbenv/rvm shims without the right environment), corrupted gem home/cache permissions, or a remote `--source` that is unreachable/has an expired TLS cert when ensure => latest triggers a remote list.
Common situations: Multi-ruby hosts where puppet picks a different ruby's gem than the app uses; ~/.gem owned by root after someone ran gem with sudo; private gem sources (Gemfury/artifactory) with expired certs or unreachable hosts; gem binary removed during a ruby upgrade.
Related errors
- puppet:// URLs are not supported as gem sources
- Could not list installed Packages: %{detail}
- puppet.tasks/invalid-metadata
- Could not set %{property} on %{resource}[%{name}]: %{detail}
- Could not delete %{resource} %{name}: %{detail}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/6c9db931d27f9682.
Report an issue: GitHub.