puppetlabs/puppet · error · Puppet::Module::Task::InvalidTask
puppet.tasks/multiple-implementations
puppet.tasks/multiple-implementations
Error message
Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them What it means
Raised as Puppet::Error by Config#parse_directive when the `url` value from device.conf fails URI.parse with URI::InvalidURIError. Only strict URI syntax errors trigger it — the scheme, host, or escaping is malformed enough that Ruby's URI parser rejects the string. %{value} echoes the exact text after the `url` keyword.
Source
Thrown at lib/puppet/module/task.rb:192
msg = _("Task metadata for task %{name} specifies missing implementation %{implementation}" % { name: name, implementation: impl['name'] })
raise InvalidTask.new(msg, 'puppet.tasks/missing-implementation', { missing: [impl['name']] })
end
{ "name" => impl['name'], "path" => path }
end
return implementations
end
# If implementations isn't defined, then we use executables matching the
# task name, and only one may exist.
implementations = executables.select { |impl| File.basename(impl, '.*') == basename }
if implementations.empty?
msg = _('No source besides task metadata was found in directory %{directory} for task %{name}') %
{ name: name, directory: directory }
raise InvalidTask.new(msg, 'puppet.tasks/no-implementation')
elsif implementations.length > 1
msg = _("Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them") %
{ name: name, directory: implementations[0] }
raise InvalidTask.new(msg, 'puppet.tasks/multiple-implementations')
end
[{ "name" => File.basename(implementations.first), "path" => implementations.first }]
end
private_class_method :find_implementations
def self.find_files(name, directory, metadata, executables, envname = nil)
# PXP agent relies on 'impls' (which is the task file) being first if there is no metadata
find_implementations(name, directory, metadata, executables) + find_extra_files(metadata, envname)
end
def self.is_tasks_metadata_filename?(name)
is_tasks_filename?(name) && name.end_with?('.json')
end
def self.is_tasks_executable_filename?(name)
is_tasks_filename?(name) && !name.end_with?('.json')
endView on GitHub (pinned to e227c27540)
Solutions
- Rewrite the url in full form with scheme and encoded credentials: `url https://user:%40pass@device.example.com:443`
- URI-encode any reserved characters in the password/host portion (RFC 3986 percent-encoding)
- Ensure the scheme matches the device type's expected transport (ssh/telnet/https per the type's documentation)
Example fix
# before [sw01.example.com] type cisco url ssh://admin:p@ss word@sw01.example.com # after [sw01.example.com] type cisco url ssh://admin:p%40ss%20word@sw01.example.com
Defensive patterns
Strategy: validation
Validate before calling
require 'uri' url = 'ssh://admin:p%40ss@sw01.example.com' URI.parse(url) # raises URI::InvalidURIError here instead of inside Puppet puts 'url ok'
Try / catch
begin config.read rescue Puppet::Error => e raise unless e.message =~ /is an invalid url/ # re-check the url line yourself: URI.parse(value) to get precise offset raise end
Prevention
- Percent-encode reserved characters (@ : / # space) in url passwords
- Always include the transport scheme matching the device type
- Run device urls through URI.parse in CI when they come from data files
When it happens
Trigger: A device url with spaces or unescaped special characters, a missing scheme (`sw01` instead of `ssh://sw01`), an unencoded password containing characters like `@` or `#`, or stray quotes/semicolons after the value. The regex captures everything after `url `, so trailing junk ends up inside %{value}.
Common situations: Passwords with reserved characters pasted into the url line; copying telnet/ssh URLs from documentation that wrap or add markup; missing scheme after template refactor.
Related errors
- puppet.tasks/missing-implementation
- puppet.tasks/no-implementation
- puppet.tasks/unreadable-metadata
- Illegal format '#{actual}' specified for value of URI type -
- URI protocol '%{protocol}' is not currently supported for fi
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/9cb50600b827e601.
Report an issue: GitHub.