puppetlabs/puppet · error · Puppet::Error
Failed to convert '%{path}' to URI: %{detail}
Error message
Failed to convert '%{path}' to URI: %{detail} What it means
Puppet::Util.path_to_uri converts a filesystem path into a file: URI: on Windows it rewrites backslashes and extracts a UNC host, then uri_encode escapes components, then splits on '?' and '#', and finally calls URI::Generic.build(params). Any exception from the build (typically URI::InvalidComponentError) is rescued and re-raised as Puppet::Error with the original path and detail (and backtrace) preserved. It is used by file resources' source handling and by metatype when recording resource locations.
Source
Thrown at lib/puppet/util.rb:308
if unc
params[:host] = unc[1]
path = unc[2]
elsif path =~ %r{^[a-z]:/}i
path = '/' + path
end
end
# have to split *after* any relevant escaping
params[:path], params[:query] = uri_encode(path).split('?')
search_for_fragment = params[:query] ? :query : :path
if params[search_for_fragment].include?('#')
params[search_for_fragment], _, params[:fragment] = params[search_for_fragment].rpartition('#')
end
begin
URI::Generic.build(params)
rescue => detail
raise Puppet::Error, _("Failed to convert '%{path}' to URI: %{detail}") % { path: path, detail: detail }, detail.backtrace
end
end
module_function :path_to_uri
# Get the path component of a URI
def uri_to_path(uri)
return unless uri.is_a?(URI)
# CGI.unescape doesn't handle space rules properly in uri paths
# URI.unescape does, but returns strings in their original encoding
path = uri_unescape(uri.path.encode(Encoding::UTF_8))
if Puppet::Util::Platform.windows? && uri.scheme == 'file'
if uri.host && !uri.host.empty?
path = "//#{uri.host}" + path # UNC
else
path.sub!(%r{^/}, '')
endView on GitHub (pinned to e227c27540)
Solutions
- Rename the offending file/path to avoid URI-reserved characters (#, ?, [, backslash)
- Escape the path before conversion: URI::DEFAULT_PARSER.escape(path) — or pass a cleaner source
- If you control the Ruby call site, rescue Puppet::Error and inspect e.cause/original detail to find the bad component
Example fix
# before
uri = Puppet::Util.path_to_uri('/srv/files/report#2?v=3.pdf')
# after
uri = Puppet::Util.path_to_uri('/srv/files/report_2_v3.pdf') Defensive patterns
Strategy: try-catch
Validate before calling
begin URI::Generic.build(scheme: 'file', path: URI::DEFAULT_PARSER.escape(path)) rescue URI::Error puts 'not convertible; sanitize the path first' end
Try / catch
begin
uri = Puppet::Util.path_to_uri(path)
rescue Puppet::Error => e
# e.message contains the original detail; fall back to raw path handling
warn "path not URI-convertible: #{e.message}"
uri = nil
end Prevention
- Avoid '#', '?', '[', ']' and backslashes in managed file names
- Sanitize user-supplied paths (escape reserved characters) before conversion
- On Windows UNC paths, keep the host component free of characters illegal in URI hosts
When it happens
Trigger: A path containing characters that uri_encode does not escape but URI::Generic.build rejects in a component (e.g. invalid host characters from a Windows UNC match, a malformed percent-escape, or reserved characters landing in the fragment/query split); calling Puppet::Util.path_to_uri directly with a malformed string; file sources with '#' or '?' mid-filename being split into fragment/query and reassembled invalidly.
Common situations: Files with '#', '?', or brackets in their names managed via a file source; Windows UNC paths with characters illegal in a URI host; deep integration code calling path_to_uri on user-supplied strings without sanitization.
Related errors
- puppet.tasks/multiple-implementations
- Illegal format '#{actual}' specified for value of URI type -
- URI protocol '%{protocol}' is not currently supported for fi
- Could not understand URL %{key}: %{detail}
- Will not remove directory backup %{newfile}; use a filebucke
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/8a1b5804039c8553.
Report an issue: GitHub.