puppetlabs/puppet · error · ArgumentError

Given multiple routes with identical path regexes: %{regexes

Error message

Given multiple routes with identical path regexes: %{regexes}

What it means

Puppet::Network::HTTP::Handler#register installs the route table for a server. It counts path_matcher occurrences across the given routes and raises ArgumentError listing the duplicated regexes if two Route objects share an identical path regex. Duplicate regexes would make routing order-dependent, so registration fails outright at server startup.

Source

Thrown at lib/puppet/network/http/handler.rb:24

require_relative '../../../puppet/network/http'
require_relative '../../../puppet/util/profiler'
require_relative '../../../puppet/util/profiler/aggregate'
require 'resolv'

module Puppet::Network::HTTP::Handler
  include Puppet::Network::HTTP::Issues

  # These shouldn't be allowed to be set by clients
  # in the query string, for security reasons.
  DISALLOWED_KEYS = %w[node ip]

  def register(routes)
    # There's got to be a simpler way to do this, right?
    dupes = {}
    routes.each { |r| dupes[r.path_matcher] = (dupes[r.path_matcher] || 0) + 1 }
    dupes = dupes.filter_map { |pm, count| pm if count > 1 }
    if dupes.count > 0
      raise ArgumentError, _("Given multiple routes with identical path regexes: %{regexes}") % { regexes: dupes.map(&:inspect).join(', ') }
    end

    @routes = routes
    Puppet.debug("Routes Registered:")
    @routes.each do |route|
      Puppet.debug(route.inspect)
    end
  end

  # Retrieve all headers from the http request, as a hash with the header names
  # (lower-cased) as the keys
  def headers(request)
    raise NotImplementedError
  end

  # The mime type is always passed to the `set_content_type` method, so
  # it is no longer necessary to retrieve the Format's mime type.
  #

View on GitHub (pinned to e227c27540)

Solutions

  1. Deduplicate routes on path_matcher before registering: handler.register(routes.uniq(&:path_matcher))
  2. Fix setup code so routes are registered exactly once (guard against double initialization on reload)
  3. Give custom mounts genuinely distinct path regexes
  4. Log each route's path_matcher at startup to spot the collision named in the error message

Example fix

# before: same route present in both lists
handler.register(routes + extra_routes)

# after: deduplicate on the path regex
handler.register((routes + extra_routes).uniq(&:path_matcher))
Defensive patterns

Strategy: validation

Validate before calling

dupes = routes.group_by(&:path_matcher).select { |_, v| v.size > 1 }.keys
raise ArgumentError, "duplicate route regexes: #{dupes.inspect}" unless dupes.empty?
handler.register(routes)

Prevention

When it happens

Trigger: Calling register with two Puppet::Network::HTTP::Route objects whose path Regex is equal: mounting the same v3 route set twice, concatenating route arrays that both contain the same entry, or custom handlers that compile to the same Regexp.

Common situations: Custom embedded Puppet masters assembling route lists from multiple sources; double registration during config reload or hot-restart; copy-pasted rack config.ru setup that runs twice.

Related errors


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