{"record":{"id":"f78232c888720438","repo":"puppetlabs/puppet","slug":"unable-to-find-loader-named-loader-name","errorCode":null,"errorMessage":"Unable to find loader named '%{loader_name}'","messagePattern":"Unable to find loader named '%(.+?)'","errorType":"exception","errorClass":"Puppet::ParseError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/loaders.rb","lineNumber":199,"sourceCode":"  # @api private\n  def self.loaders\n    loaders = Puppet.lookup(:loaders) { nil }\n    raise Puppet::ParseError, _(\"Internal Error: Puppet Context ':loaders' missing\") if loaders.nil?\n\n    loaders\n  end\n\n  # Lookup a loader by its unique name.\n  #\n  # @param [String] loader_name the name of the loader to lookup\n  # @return [Loader] the found loader\n  # @raise [Puppet::ParserError] if no loader is found\n  def [](loader_name)\n    loader = @loaders_by_name[loader_name]\n    if loader.nil?\n      # Unable to find the module private loader. Try resolving the module\n      loader = private_loader_for_module(loader_name[0..-9]) if loader_name.end_with?(' private')\n      raise Puppet::ParseError, _(\"Unable to find loader named '%{loader_name}'\") % { loader_name: loader_name } if loader.nil?\n    end\n    loader\n  end\n\n  # Finds the appropriate loader for the given `module_name`, or for the environment in case `module_name`\n  # is `nil` or empty.\n  #\n  # @param module_name [String,nil] the name of the module\n  # @return [Loader::Loader] the found loader\n  # @raise [Puppet::ParseError] if no loader can be found\n  # @api private\n  def find_loader(module_name)\n    if module_name.nil? || EMPTY_STRING == module_name\n      # Use the public environment loader\n      public_environment_loader\n    else\n      # TODO : Later check if definition is private, and then add it to private_loader_for_module\n      #","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/loaders.rb#L181-L217","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Verify a loader name will resolve before using it\nloaders = Puppet.lookup(:loaders)\nmodule_name = loader_name.sub(/ private\\z/, '')\nenv = loaders.environment\nunless env.modules.any? { |m| m.name == module_name }\n  raise ArgumentError, \"module '#{module_name}' is not in the modulepath of environment '#{env.name}'\"\nend\nloader = loaders[loader_name]","typeGuard":null,"tryCatchPattern":"begin\n  loader = Puppet.lookup(:loaders)[name]\nrescue Puppet::ParseError => e\n  # name is stale (module removed/renamed) — regenerate artifacts referencing it\n  logger.warn(\"stale loader reference #{name}: #{e.message}\")\n  fallback_loader = Puppet.lookup(:loaders).environment_loader\nend","preventionTips":["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."],"tags":["puppet","loader","modulepath","module-not-found","parseerror"],"backgroundTag":"puppet-loader-not-found","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}