puppetlabs/puppet · critical · Puppet::HTTP::RouteError

No more routes to #{name}

Error message

No more routes to #{name}

What it means

After the session walks its resolver chain (SRV record resolver, then server_list resolver) without any resolver producing a usable service, it raises Puppet::HTTP::RouteError. This is the terminal failure of service discovery: no explicit URL was given, nothing was cached, and every configured discovery mechanism came up empty.

Source

Thrown at lib/puppet/http/session.rb:79

    cached = @resolved_services[name]
    return cached if cached

    canceled = false
    canceled_handler = ->(cancel) { canceled = cancel }

    @resolvers.each do |resolver|
      Puppet.debug("Resolving service '#{name}' using #{resolver.class}")
      service = resolver.resolve(self, name, ssl_context: ssl_context, canceled_handler: canceled_handler)
      if service
        @resolved_services[name] = service
        Puppet.debug("Resolved service '#{name}' to #{service.url}")
        return service
      elsif canceled
        break
      end
    end

    raise Puppet::HTTP::RouteError, "No more routes to #{name}"
  end

  # Collect per-site server versions. This will allow us to modify future
  # requests based on the version of puppetserver we are talking to.
  #
  # @param [Puppet::HTTP::Response] response the request response containing headers
  #
  # @api private
  def process_response(response)
    version = response[Puppet::HTTP::HEADER_PUPPET_VERSION]
    if version
      site = Puppet::HTTP::Site.from_uri(response.url)
      @server_versions[site] = version
    end
  end

  # Determine if a session supports a capability. Depending on the server version
  # we are talking to, we know certain features are available or not. These

View on GitHub (pinned to e227c27540)

Solutions

  1. Run with --debug and read the 'Resolving service ... using' lines, then verify each candidate host:port is reachable (curl -k https://server:8140/status/v1/simple)
  2. Fix or remove dns_srv_domain and correct server_list so at least one route is valid
  3. Bypass discovery for one-offs by passing url: to route_to (explicit host and port skips resolvers)
  4. If a firewall or NAT is involved, open TCP 8140 to every master in server_list before retrying

Example fix

# before: dns_srv_domain = example.com with no SRV records, no server_list
session.route_to(:puppet) # => Puppet::HTTP::RouteError: No more routes to puppet

# after: puppet.conf -> server_list = puppet1.example.com,puppet2.example.com
session.route_to(:puppet)
# or explicit bypass (ruby):
session.route_to(:puppet, url: URI('https://puppet1.example.com:8140'))
Defensive patterns

Strategy: try-catch

Validate before calling

# ruby
require 'socket'
reachable = Puppet[:server_list].split(',').any? do |h|
  begin
    TCPSocket.new(h.strip, Puppet[:serverport]).tap(&:close); true
  rescue StandardError
    false
  end
end
raise 'no puppetserver reachable' unless reachable

Type guard

def explicit_route?(url)
  url.is_a?(URI) && !url.host.nil? && !url.host.empty?
end

Try / catch

begin
  service = session.route_to(:puppet)
rescue Puppet::HTTP::RouteError => e
  Puppet.err(e.message)
  service = session.route_to(:puppet, url: KNOWN_MASTER_URI)  # explicit fallback
end

Prevention

When it happens

Trigger: dns_srv_domain is set and the SRV lookup yields no usable records while server_list is empty or all its entries fail their probe; every host:port candidate in server_list is unreachable (refused/timeout on 8140); the explicit url: bypass was not used.

Common situations: Wrong or stale server_list in puppet.conf; load balancer VIP down; firewall blocking TCP 8140; DNS SRV records (_x-puppet._tcp) deleted while dns_srv_domain remains set; TLS probe of each candidate failing during bootstrap before certificates are issued.

Related errors


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