puppetlabs/puppet · error · ArgumentError
Could not understand URL %{key}: %{detail}
Error message
Could not understand URL %{key}: %{detail} What it means
When a request key is a URI, Request#set_uri_key runs URI.parse(Puppet::Util.uri_encode(key)); any failure raises ArgumentError with the key and detail. This happens for keys that look like URLs but violate RFC 3986 after encoding: embedded spaces or brackets that survive encoding, 'host:' with no scheme text, control characters, or unescaped percent sequences like '%' alone (bad %-encoding).
Source
Thrown at lib/puppet/indirector/request.rb:168
private
def set_attributes(options)
OPTION_ATTRIBUTES.each do |attribute|
if options.include?(attribute.to_sym)
send(attribute.to_s + "=", options[attribute])
options.delete(attribute)
end
end
end
# Parse the key as a URI, setting attributes appropriately.
def set_uri_key(key)
@uri = key
begin
# calling uri_encode for UTF-8 characters will % escape them and keep them UTF-8
uri = URI.parse(Puppet::Util.uri_encode(key))
rescue => detail
raise ArgumentError, _("Could not understand URL %{key}: %{detail}") % { key: key, detail: detail }, detail.backtrace
end
# Just short-circuit these to full paths
if uri.scheme == "file"
@key = Puppet::Util.uri_to_path(uri)
return
end
@server = uri.host if uri.host && !uri.host.empty?
# If the URI class can look up the scheme, it will provide a port,
# otherwise it will default to '0'.
if uri.port.to_i == 0 and uri.scheme == "puppet"
@port = Puppet.settings[:serverport].to_i
else
@port = uri.port.to_i
end
View on GitHub (pinned to e227c27540)
Solutions
- Inspect the exact key in the message and fix the bad characters (unescaped %, spaces, brackets)
- Build keys with URI and escape components separately: URI::Generic.build(...) or ERB::Util.url_encode on path segments
- Use Puppet::Util.uri_encode on the raw string before it becomes a key, rather than hand-concatenating
- For local paths, prefer plain filesystem paths (file scheme is short-circuited to a path) and avoid embedding them in pseudo-URLs
Example fix
# before
key = "puppet:///files/my file.txt".sub('files', 'files') # raw space survives
URI.parse(key) # => ArgumentError: Could not understand URL ...
# after
require 'erb'
key = "puppet:///files/#{ERB::Util.url_encode('my file.txt')}" # my%20file.txt Defensive patterns
Strategy: validation
Validate before calling
begin
URI.parse(Puppet::Util.uri_encode(key))
rescue URI::Error, ArgumentError => e
raise ArgumentError, "refusing to build request with unparseable key #{key.inspect}: #{e.message}"
end Try / catch
begin request = Puppet::Indirection::Request.new(indirection, method, key, nil) rescue ArgumentError => e raise unless e.message =~ /Could not understand URL/ key = ERB::Util.url_encode(key) # normalize and retry once request = Puppet::Indirection::Request.new(indirection, method, key, nil) end
Prevention
- Percent-encode path components at construction time with ERB::Util.url_encode
- Validate user-supplied keys against /\A[\w.\-/:%]+\z/ before they reach the indirector
- Build URIs with URI::Generic.build instead of string concatenation
When it happens
Trigger: Passing keys such as 'puppet://server:8140/production/%%' (bad percent escape), 'file:///tmp/my file.yaml' handled wrongly, or resource keys with raw spaces/control characters to indirector APIs that treat keys as URIs (puppet filebucket, file_content/file_metadata REST keys, catalog with URI-style node keys).
Common situations: Shell quoting mistakes that inject spaces into resource references; user-supplied paths used as indirection keys without escaping; filebucket or fileserver URIs built by string concatenation instead of URI libraries.
Related errors
- Could not find indirection '%{indirection}'
- You can only save objects that respond to :name
- puppet.tasks/multiple-implementations
- puppet.tasks/unparseable-metadata
- Illegal format '#{actual}' specified for value of URI type -
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/0926e590efc4a8c8.
Report an issue: GitHub.