puppetlabs/puppet · error

Could not select a functional puppet server from server_list

Error message

Could not select a functional puppet server from server_list: '%{server_list}'

What it means

Raised (or logged) by Puppet::Configurer after find_functional_server probed every entry in server_list and none answered. When usecacheonfailure is true the agent degrades: pluginsync is disabled, the first server in the list is selected, and a cached catalog is used. Otherwise Puppet::Error stops the run.

Source

Thrown at lib/puppet/configurer.rb:329

    completed = nil
    begin
      # Skip failover logic if the server_list setting is empty
      do_failover = Puppet.settings[:server_list] && !Puppet.settings[:server_list].empty?

      # When we are passed a catalog, that means we're in apply
      # mode. We shouldn't try to do any failover in that case.
      if options[:catalog].nil? && do_failover
        server, port = find_functional_server
        if server.nil?
          detail = _("Could not select a functional puppet server from server_list: '%{server_list}'") % { server_list: Puppet.settings.value(:server_list, Puppet[:environment].to_sym, true) }
          if Puppet[:usecacheonfailure]
            options[:pluginsync] = false
            @running_failure = true

            server = Puppet[:server_list].first[0]
            port = Puppet[:server_list].first[1] || Puppet[:serverport]

            Puppet.err(detail)
          else
            raise Puppet::Error, detail
          end
        else
          # TRANSLATORS 'server_list' is the name of a setting and should not be translated
          Puppet.debug _("Selected puppet server from the `server_list` setting: %{server}:%{port}") % { server: server, port: port }
          report.server_used = "#{server}:#{port}"
        end
        Puppet.override(server: server, serverport: port) do
          completed = run_internal(options)
        end
      else
        completed = run_internal(options)
      end
    ensure
      # we may sleep for awhile, close connections now
      Puppet.runtime[:http].close
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Verify each entry responds: `curl -k https://<host>:8140/status/v1/simple`
  2. Check server_list syntax — comma-separated, optional :port per entry — via `puppet config print server_list`
  3. Start/restart puppetserver on the listed hosts and inspect its logs
  4. Open TCP 8140 in firewalls and fix DNS for every listed host
  5. If degraded mode is intended, confirm usecacheonfailure=true so cached catalogs carry the run

Example fix

# before (puppet.conf)
server_list = puppet:puppet2

# after
server_list = puppet.example.com:8140,puppet2.example.com:8140
Defensive patterns

Strategy: validation

Validate before calling

require 'socket'

Puppet[:server_list].each do |host, port|
  port ||= Puppet[:serverport]
  begin
    TCPSocket.new(host, port).close
  rescue SystemCallError, IOError
    warn "#{host}:#{port} unreachable"
  end
end

Try / catch

begin
  Puppet::Configurer.new(node).run
rescue Puppet::Error => e
  raise unless e.message.include?('functional puppet server')
  report_all_servers_down   # surface which entries failed; cached catalog may already be in use
end

Prevention

When it happens

Trigger: A catalog run with options[:catalog] nil and failover active, where every 'host[:port]' in server_list fails the liveness probe: puppetserver down, 8140 blocked by firewall, DNS resolving wrong, TLS rejected, or server_list formatted so the entries are unusable.

Common situations: Puppet server stopped after an upgrade; load balancer drained; security group closed 8140; typo'd server_list such as 'puppet:puppet2' instead of comma-separated entries; IPv6/IPv4 resolution differences.

Related errors


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