puppetlabs/puppet · error · Puppet::ParseError

Unable to find loader named

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'.

Solutions

  1. Verify the module exists under the environment's modulepath and has valid metadata (metadata.json).
  2. 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.
  3. Regenerate/re-upload artifacts that embed the stale loader name (e.g. re-compile plans after renaming a module).
  4. 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

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


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

Appendix: 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)