puppetlabs/puppet · error · RuntimeError

Could not call '%{method}' on '%{indirection}': %{detail}

Error message

Could not call '%{method}' on '%{indirection}': %{detail}

What it means

Puppet::Indirector::Face#call_indirection_method is the funnel behind every 'puppet <indirection> <action>' CLI subcommand (facts find, certificate sign, node find, ...). Any exception from the underlying terminus is logged with backtrace and re-raised as RuntimeError 'Could not call <method> on <indirection>: <detail>' — it is a wrapper, and the actionable cause is always the detail text and the logged exception.

Source

Thrown at lib/puppet/indirector/face.rb:53

    Puppet::Indirector::Indirection.instances.collect(&:to_s).sort
  end

  def self.terminus_classes(indirection)
    Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect(&:to_s).sort
  end

  def call_indirection_method(method, key, options)
    begin
      if method == :save
        # key is really the instance to save
        result = indirection.__send__(method, key, nil, options)
      else
        result = indirection.__send__(method, key, options)
      end
    rescue => detail
      message = _("Could not call '%{method}' on '%{indirection}': %{detail}") % { method: method, indirection: indirection_name, detail: detail }
      Puppet.log_exception(detail, message)
      raise RuntimeError, message, detail.backtrace
    end

    result
  end

  action :destroy do
    summary _("Delete an object.")
    arguments _("<key>")
    when_invoked { |key, _options| call_indirection_method :destroy, key, {} }
  end

  action :find do
    summary _("Retrieve an object by name.")
    arguments _("[<key>]")
    when_invoked do |*args|
      # Default the key to Puppet[:certname] if none is supplied
      if args.length == 1
        key = Puppet[:certname]

View on GitHub (pinned to e227c27540)

Solutions

  1. Run the same command with --trace (and --debug) to get the original backtrace logged when the wrapper fired
  2. Fix the named detail cause: terminus setting, connectivity, permissions, or SSL state as indicated
  3. Reproduce outside the face by calling the indirection in Ruby to isolate face-specific option bugs

Example fix

# before
$ puppet facts find node1.example.com
# Error: Could not call 'find' on 'facts': ...

# after
$ puppet facts find node1.example.com --trace --debug
# read the original exception; fix facts_terminus/server, then rerun
Defensive patterns

Strategy: try-catch

Validate before calling

# ruby
# pre-flight the terminus before invoking the face
if opts[:terminus] == 'rest'
  require 'socket'
  TCPSocket.new(Puppet[:server], Puppet[:serverport]).close
end
Puppet::Face[:facts, :current].find(name)

Type guard

def indirection_callable?(face_name, method)
  Puppet::Face[face_name, :current].respond_to?(method)
end

Try / catch

begin
  face.call_indirection_method(method, key, options)
rescue RuntimeError => e
  raise unless e.message.start_with?('Could not call')
  Puppet.err(e.message)  # wrapper text names the method and indirection
  nil
end

Prevention

When it happens

Trigger: puppet facts find node1 --terminus rest when the server is unreachable (wraps the network error); certificate generation with broken SSL state; any terminus rejecting the option combination the face forwarded.

Common situations: CLI usage against a misconfigured terminus (facts_terminus=rest with a wrong server setting); running face commands as the wrong user so file or SSL access fails; debugging only from the wrapper message instead of the --trace output.

Related errors


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