puppetlabs/puppet · error · Puppet::Error

cannot lookup multiple files

Error message

cannot lookup multiple files

What it means

The http file_metadata terminus serves metadata for a single HTTP(S) URL via HEAD, falling back to a one-byte Range GET when the server answers 403/405 (e.g. S3 presigned URLs). Puppet's search action means metadata for many files / recursive traversal, which plain web servers cannot express, so search unconditionally raises Puppet::Error 'cannot lookup multiple files'.

Source

Thrown at lib/puppet/indirector/file_metadata/http.rb:34

    uri = URI(request.uri)
    client = Puppet.runtime[:http]
    head = client.head(uri, options: { include_system_store: true })

    return create_httpmetadata(head, checksum_type) if head.success?

    case head.code
    when 403, 405
      # AMZ presigned URL and puppetserver may return 403
      # instead of 405. Fallback to partial get
      get = partial_get(client, uri)
      return create_httpmetadata(get, checksum_type) if get.success?
    end

    nil
  end

  def search(request)
    raise Puppet::Error, _("cannot lookup multiple files")
  end

  private

  def partial_get(client, uri)
    client.get(uri, headers: { 'Range' => 'bytes=0-0' }, options: { include_system_store: true })
  end

  def create_httpmetadata(http_request, checksum_type)
    metadata = Puppet::FileServing::HttpMetadata.new(http_request)
    metadata.checksum_type = checksum_type if checksum_type
    metadata.collect
    metadata
  end
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Point each resource at a single file URL and generate one resource per file (e.g. from a manifest loop or a generated list).
  2. Remove recurse / recurse_remote from resources whose source scheme is http or https.
  3. If recursion is required, sync the remote tree into a module or another puppet-served location and use a puppet:/// source.

Example fix

# before
file { '/opt/app':
  ensure  => directory,
  recurse => true,
  source  => 'https://repo.example.com/app/1.2.3/',
}
# Error: cannot lookup multiple files

# after: stage the tree in a module, recurse over puppet://
file { '/opt/app':
  ensure  => directory,
  recurse => true,
  source  => 'puppet:///modules/app_files/1.2.3',
}
Defensive patterns

Strategy: validation

Validate before calling

def http_source?(uri)
  %w[http https].include?(URI.parse(uri).scheme.to_s)
end

raise ArgumentError, 'http(s) sources cannot be recursive' if http_source?(source) && opts[:recurse]

Type guard

def single_http_file?(uri)
  u = URI.parse(uri.to_s)
  %w[http https].include?(u.scheme.to_s) && !u.path.to_s.end_with?('/')
end

Prevention

When it happens

Trigger: A file (or similar) resource whose source is 'http://' or 'https://' combined with recurse => true or sources => containing multiple http URLs; a Ruby call to Puppet::FileServing::Metadata.indirection.search with an http(s) URI.

Common situations: Porting a recursive copy from puppet:// to a web server or object store; pointing file resources at artifact directories served by nginx/S3; expecting directory listing semantics from presigned URLs.

Related errors


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