{"record":{"id":"eab4deb905dbd7bd","repo":"puppetlabs/puppet","slug":"could-not-find-terminus-terminus-class-for-indi-eab4de","errorCode":null,"errorMessage":"Could not find terminus %{terminus_class} for indirection %{indirection}","messagePattern":"Could not find terminus %(.+?) for indirection %(.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/indirection.rb","lineNumber":376,"sourceCode":"  # @return [Puppet::Indirector::Terminus] terminus instance (usually a subclass\n  #   of Puppet::Indirector::Terminus) for this request\n  def prepare(request)\n    # Pick our terminus.\n    terminus_name = terminus_class\n\n    dest_terminus = terminus(terminus_name)\n    check_authorization(request, dest_terminus)\n    dest_terminus.validate(request)\n\n    dest_terminus\n  end\n\n  # Create a new terminus instance.\n  def make_terminus(terminus_class)\n    # Load our terminus class.\n    klass = Puppet::Indirector::Terminus.terminus_class(name, terminus_class)\n    unless klass\n      raise ArgumentError, _(\"Could not find terminus %{terminus_class} for indirection %{indirection}\") % { terminus_class: terminus_class, indirection: name }\n    end\n\n    klass.new\n  end\nend\n","sourceCodeStart":358,"sourceCodeEnd":382,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/indirection.rb#L358-L382","documentation":"make_terminus resolves the terminus class again when instantiating a terminus (called from Indirection#terminus); if Puppet::Indirector::Terminus.terminus_class returns nil it raises ArgumentError 'Could not find terminus ... for indirection ...'. This fires when the setting changed after validation or when code requests a terminus by name that is not loadable in the current process.","triggerScenarios":"Ruby code calling indirection.terminus(:some_name) with a name that is not registered for that indirection; a terminus file removed or its gem uninstalled between configuration and use; a custom terminus whose require fails lazily so terminus_class returns nil.","commonSituations":"Pluginsync-delivered termini present on agents but not on compile servers; gems uninstalled during cleanup; name case mismatches (Json vs json); half-completed upgrades where config references a terminus only shipped in the newer gem.","solutions":["Same check as at assignment time: confirm Puppet::Indirector::Terminus.terminus_classes(<indirection>) actually lists the name in this process.","Install or require the gem/module providing the terminus on the host running the code.","Prefer the validated path (indirection.terminus_class = name) over direct terminus(name) lookups.","Add a boot-time smoke test that requires the terminus file so failures surface at startup with a clear message."],"exampleFix":"# before\nterminus = Puppet::Resource::Catalog.indirection.terminus(:custom)\n# ArgumentError: Could not find terminus custom for indirection catalog\n\n# after\ngem 'puppet-catalog-custom' # installed and required first\nPuppet::Resource::Catalog.indirection.terminus(:custom)","handlingStrategy":"validation","validationCode":"name = :json\nunless Puppet::Indirector::Terminus.terminus_class(indirection.name, name)\n  raise ArgumentError, 'cannot instantiate missing terminus: ' + name.to_s\nend\nindirection.terminus(name)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer the validated terminus_class= path over direct terminus(name) lookups.","Add boot-time checks that require custom terminus files.","Keep the gems that supply termini installed on every host that sets them."],"tags":["puppet","indirector","terminus","lazy-loading","plugin-loading"],"backgroundTag":"unknown-backend-implementation","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}