puppetlabs/puppet · error · Puppet::Error

Failed to convert ' ' to URI

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.

Solutions

  1. Rename the offending file/path to avoid URI-reserved characters (#, ?, [, backslash)
  2. Escape the path before conversion: URI::DEFAULT_PARSER.escape(path) — or pass a cleaner source
  3. 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

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


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

Appendix: 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{^/}, '')
      end

View on GitHub (pinned to e227c27540)