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
- Deduplicate routes on path_matcher before registering: handler.register(routes.uniq(&:path_matcher))
- Fix setup code so routes are registered exactly once (guard against double initialization on reload)
- Give custom mounts genuinely distinct path regexes
- 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
- Deduplicate by path regex whenever routes are assembled dynamically
- Make registration idempotent: track whether register already ran for this handler
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
- The indirection name must be purely alphanumeric, not '%{ind
- Indirection '%{indirection_name}' does not match url prefix
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/ebed7e0035b28836.
Report an issue: GitHub.