puppetlabs/puppet · error · Puppet::Module::Task::InvalidMetadata
puppet.task/invalid-metadata
puppet.task/invalid-metadata
Error message
Files specified in task metadata cannot include a trailing slash: %{file} What it means
Raised as ArgumentError by Puppet::Util::Ldap::Manager#entry2provider when the entry hash passed in has no 'dn' key. The conversion immediately needs the distinguished name to derive the resource name (it pops the single dn value and strips it down to the rdn value), so an entry without dn cannot be converted at all. This is a contract violation between the LDAP search layer and the manager, not an I/O failure.
Source
Thrown at lib/puppet/module/task.rb:147
end
unless File.exist?(path)
msg = _("Could not find %{path} on disk" % { path: path })
raise InvalidFile, msg
end
last_char = file[-1] == '/'
if File.directory?(path)
unless last_char
msg = _("Directories specified in task metadata must include a trailing slash: %{dir}" % { dir: file })
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
dir_files = Dir.glob("#{path}**/*").select { |f| File.file?(f) }
dir_files.map { |f| get_file_details(f, pup_module) }
else
if last_char
msg = _("Files specified in task metadata cannot include a trailing slash: %{file}" % { file: file })
raise InvalidMetadata.new(msg, 'puppet.task/invalid-metadata')
end
get_file_details(path, pup_module)
end
end
end
private_class_method :find_extra_files
# Executables list should contain the full path of all possible implementation files
def self.find_implementations(name, directory, metadata, executables)
basename = name.split('::')[1] || 'init'
# If 'implementations' is defined, it needs to mention at least one
# implementation, and everything it mentions must exist.
metadata ||= {}
if metadata.key?('implementations')
unless metadata['implementations'].is_a?(Array)
msg = _("Task metadata for task %{name} does not specify implementations as an array" % { name: name })
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
endView on GitHub (pinned to e227c27540)
Solutions
- Ensure the search requests the dn (or that the client keeps it in the attribute hash) before calling entry2provider
- Fix fixture/spec hashes to include 'dn' => ['cn=name,ou=...,dc=...']
- Guard at the call site: skip or log entries lacking 'dn' instead of passing them through
Example fix
# before
entry = { 'cn' => ['web01'], 'objectclass' => ['top'] }
manager.entry2provider(entry) # raises ArgumentError
# after
entry = { 'dn' => ['cn=web01,ou=hosts,dc=example,dc=com'], 'cn' => ['web01'], 'objectclass' => ['top'] }
manager.entry2provider(entry) Defensive patterns
Strategy: type-guard
Type guard
def convertible_entry?(entry)
entry.is_a?(Hash) && entry['dn'].is_a?(Array) && !entry['dn'].empty?
end
results.select { |e| convertible_entry?(e) }.each { |e| manager.entry2provider(e) } Try / catch
begin
manager.entry2provider(entry)
rescue ArgumentError => e
raise unless e.message =~ /Could not get dn/
Puppet.debug("skipping LDAP entry without dn: #{entry.inspect}")
end Prevention
- Always request/keep dn in LDAP search attribute lists
- Include 'dn' in every rspec fixture entry used with the manager
- Skip-and-log entries failing the guard instead of letting one bad entry abort the batch
When it happens
Trigger: Calling manager.entry2provider(entry) with a hash built by hand or by a search whose attribute list excludes dn; tests with fixture entries that omit 'dn'; custom code reusing the manager on entries obtained from a different LDAP client that returns dn separately from attributes.
Common situations: rspec fixtures copied from ldapsearch output without the dn: line; code paths that filter search results and accidentally drop the dn pair; upgrades of client libraries that stop merging dn into the attribute hash.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- PathPatterns cannot be created with a zero byte.
- Request to Puppet Forge failed. Detail: %{detail}.
- Unable to verify the SSL certificate at %{uri}
- Unable to connect to the server at %{uri}. Detail: %{detail}
- puppet.plans/invalid-name
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/2bc9d25f497adc60.
Report an issue: GitHub.