puppetlabs/puppet · error · Puppet::ParseError
Unable to find loader named '%{loader_name}'
Error message
Unable to find loader named '%{loader_name}' What it means
Loaders#[] resolves a loader by its unique name; the lookup table is @loaders_by_name, populated from the modules and environment actually loaded. If the name is missing, it retries for module-private loaders by stripping a trailing ' private' suffix and asking private_loader_for_module; only if that also fails does it raise Puppet::ParseError. In practice the name comes from a module, so this error means 'the module behind this loader name is not loaded/known to this environment'.
Source
Thrown at lib/puppet/pops/loaders.rb:199
# @api private
def self.loaders
loaders = Puppet.lookup(:loaders) { nil }
raise Puppet::ParseError, _("Internal Error: Puppet Context ':loaders' missing") if loaders.nil?
loaders
end
# Lookup a loader by its unique name.
#
# @param [String] loader_name the name of the loader to lookup
# @return [Loader] the found loader
# @raise [Puppet::ParserError] if no loader is found
def [](loader_name)
loader = @loaders_by_name[loader_name]
if loader.nil?
# Unable to find the module private loader. Try resolving the module
loader = private_loader_for_module(loader_name[0..-9]) if loader_name.end_with?(' private')
raise Puppet::ParseError, _("Unable to find loader named '%{loader_name}'") % { loader_name: loader_name } if loader.nil?
end
loader
end
# Finds the appropriate loader for the given `module_name`, or for the environment in case `module_name`
# is `nil` or empty.
#
# @param module_name [String,nil] the name of the module
# @return [Loader::Loader] the found loader
# @raise [Puppet::ParseError] if no loader can be found
# @api private
def find_loader(module_name)
if module_name.nil? || EMPTY_STRING == module_name
# Use the public environment loader
public_environment_loader
else
# TODO : Later check if definition is private, and then add it to private_loader_for_module
#View on GitHub (pinned to e227c27540)
Solutions
- Verify the module exists under the environment's modulepath and has valid metadata (metadata.json).
- Check the exact spelling of the name passed to [] — for private loaders it must be '<module> private' with the space, and the module segment must match a loaded module.
- Regenerate/re-upload artifacts that embed the stale loader name (e.g. re-compile plans after renaming a module).
- Run `puppet module list --environment <env>` (or equivalent) to see which module loaders were actually created.
Defensive patterns
Strategy: validation
Validate before calling
# Verify a loader name will resolve before using it
loaders = Puppet.lookup(:loaders)
module_name = loader_name.sub(/ private\z/, '')
env = loaders.environment
unless env.modules.any? { |m| m.name == module_name }
raise ArgumentError, "module '#{module_name}' is not in the modulepath of environment '#{env.name}'"
end
loader = loaders[loader_name] Try / catch
begin
loader = Puppet.lookup(:loaders)[name]
rescue Puppet::ParseError => e
# name is stale (module removed/renamed) — regenerate artifacts referencing it
logger.warn("stale loader reference #{name}: #{e.message}")
fallback_loader = Puppet.lookup(:loaders).environment_loader
end Prevention
- Keep module names stable across control-repo revisions; when renaming, recompile dependent plans/artifacts.
- Validate modulepath and metadata.json in CI (`puppet module list`) before depending on a module's loader.
- Treat loader names as derived data — never hardcode them in serialized artifacts when the module name can be computed.
When it happens
Trigger: Calling Puppet.lookup(:loaders)['mymodule private'] (or any loader name) when 'mymodule' is absent from the modulepath; code or serialized plan/deferred metadata referencing a module that was removed or renamed; a typo in the module name portion of the loader name.
Common situations: Module removed or renamed between control-repo revisions while cached artifacts (compiled plans, deferred values, reports) still reference it; modulepath misconfiguration so Puppet never loaded the module; environment isolation differences between nodes.
Related errors
- Invalid module name '%{name}'; module names must match eithe
- '%{module_name}' (%{version}) requested; installation confli
- Could not %{action} '%{module_name}'; module appears in mult
- Could not %{action} '%{module_name}'; module is not installe
- Could not %{action} '%{module_name}'; module appears in mult
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/f78232c888720438.
Report an issue: GitHub.