{"record":{"id":"98cbecd7f9c11756","repo":"puppetlabs/puppet","slug":"could-not-find-terminus-terminus-class-for-indi","errorCode":null,"errorMessage":"Could not find terminus %{terminus_class} for indirection %{name}","messagePattern":"Could not find terminus %(.+?) for indirection %(.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/indirection.rb","lineNumber":188,"sourceCode":"\n  def reset_terminus_class\n    @terminus_class.value = nil\n  end\n\n  # Specify the terminus class to use.\n  def terminus_class=(klass)\n    validate_terminus_class(klass)\n    @terminus_class.value = klass\n  end\n\n  # This is used by terminus_class= and cache=.\n  def validate_terminus_class(terminus_class)\n    unless terminus_class and terminus_class.to_s != \"\"\n      raise ArgumentError, _(\"Invalid terminus name %{terminus_class}\") % { terminus_class: terminus_class.inspect }\n    end\n\n    unless Puppet::Indirector::Terminus.terminus_class(name, terminus_class)\n      raise ArgumentError, _(\"Could not find terminus %{terminus_class} for indirection %{name}\") %\n                           { terminus_class: terminus_class, name: name }\n    end\n  end\n\n  # Expire a cached object, if one is cached.  Note that we don't actually\n  # remove it, we expire it and write it back out to disk.  This way people\n  # can still use the expired object if they want.\n  def expire(key, options = {})\n    request = request(:expire, key, nil, options)\n\n    return nil unless cache? && !request.ignore_cache_save?\n\n    instance = cache.find(request(:find, key, nil, options))\n    return nil unless instance\n\n    Puppet.info _(\"Expiring the %{cache} cache of %{instance}\") % { cache: name, instance: instance.name }\n\n    # Set an expiration date in the past","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/indirection.rb#L170-L206","documentation":"After the blank check, validate_terminus_class resolves the terminus class via Puppet::Indirector::Terminus.terminus_class(name, terminus_class), which requires 'puppet/indirector/<indirection>/<terminus>'. If no such class exists, ArgumentError 'Could not find terminus X for indirection Y' is raised at assignment time, before any request is made.","triggerScenarios":"A misspelled terminus in puppet.conf (node_terminus = exec-like typos, catalog_terminus = catelog); a custom terminus whose gem or module is not installed on this node; a terminus name that exists only for a different indirection or puppet version.","commonSituations":"Custom termini shipped as gems present on compile servers but missing on agents (or vice versa); documentation copy-paste across puppet versions where names changed; PE/open-source version drift.","solutions":["List valid names for the indirection: Puppet::Indirector::Terminus.terminus_classes(:catalog), or inspect lib/puppet/indirector/<indirection>/ on the installed gem.","Install or require the gem/module that provides the custom terminus on the failing host.","Fix spelling and confirm the name matches the indirection (e.g. compiler for catalog on a server).","Confirm the setting sits in the right run-mode section ([agent] vs [server]/[master])."],"exampleFix":"# before\n[main]\ncatalog_terminus = catelog # typo\n\n# after\n[main]\ncatalog_terminus = compiler","handlingStrategy":"validation","validationCode":"desired = 'compiler'\nunless Puppet::Indirector::Terminus.terminus_class(:catalog, desired)\n  raise ArgumentError, 'terminus not installed: ' + desired\nend\nPuppet::Resource::Catalog.indirection.terminus_class = desired","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Smoke-test custom termini by requiring them before switching settings.","Pin gem versions that provide termini alongside the puppet version.","Automate config validation with puppet config print in CI."],"tags":["puppet","indirector","terminus","plugin-loading","configuration"],"backgroundTag":"unknown-backend-implementation","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}