puppetlabs/puppet · error · ArgumentError
Paths to keyfiles must be absolute, not %{entry}
Error message
Paths to keyfiles must be absolute, not %{entry} What it means
Raised by the validate block of the `purge_ssh_keys` property on the `user` type for each string entry that is neither an absolute path (Puppet::Util.absolute_path?, platform-aware) nor prefixed with ~/ or %h/. Puppet generates ssh_authorized_key purge resources from these paths and refuses relative ones because purging by a relative path would resolve against the agent's cwd unpredictably. %h expands to the user's home directory at munge time.
Source
Thrown at lib/puppet/type/user.rb:746
the user's home directory."
defaultto :false
# Use Symbols instead of booleans until PUP-1967 is resolved.
newvalues(:true, :false)
validate do |value|
if [:true, :false].include? value.to_s.intern
return
end
value = [value] if value.is_a?(String)
if value.is_a?(Array)
value.each do |entry|
raise ArgumentError, _("Each entry for purge_ssh_keys must be a string, not a %{klass}") % { klass: entry.class } unless entry.is_a?(String)
valid_home = Puppet::Util.absolute_path?(entry) || entry =~ %r{^~/|^%h/}
raise ArgumentError, _("Paths to keyfiles must be absolute, not %{entry}") % { entry: entry } unless valid_home
end
return
end
raise ArgumentError, _("purge_ssh_keys must be true, false, or an array of file names, not %{value}") % { value: value.inspect }
end
munge do |value|
# Resolve string, boolean and symbol forms of true and false to a
# single representation.
case value
when :false, false, "false"
[]
when :true, true, "true"
home = homedir
home ? ["#{home}/.ssh/authorized_keys"] : []
else
# value can be a string or array - munge each value
[value].flatten.filter_map do |entry|View on GitHub (pinned to e227c27540)
Solutions
- Use an absolute path: `purge_ssh_keys => ['/etc/ssh/keys/alice/authorized_keys']`
- Or a home-relative prefix: `=> ['~/.ssh/authorized_keys']` or `=> ['%h/.ssh/authorized_keys']`
- Prefix generated paths explicitly: "${home}/.ssh/authorized_keys"
Example fix
# before
user { 'alice':
ensure => present,
purge_ssh_keys => ['.ssh/id_rsa'],
}
# after
user { 'alice':
ensure => present,
purge_ssh_keys => ['~/.ssh/authorized_keys', '%h/.ssh/id_rsa'],
} Defensive patterns
Strategy: validation
Validate before calling
require 'puppet/util'
valid = keys.all? { |k| Puppet::Util.absolute_path?(k) || k.start_with?('~/', '%h/') }
raise ArgumentError, "purge_ssh_keys paths must be absolute or ~/ or %h/ prefixed: #{keys.inspect}" unless valid Type guard
def absolute_or_home_prefixed?(entry)
entry.is_a?(String) && (Puppet::Util.absolute_path?(entry) || entry =~ %r{\A(~|%h)/})
end Prevention
- Standardize on '~/.ssh/authorized_keys' or '%h/.ssh/authorized_keys' for home-relative keys
- Type params as Array[Stdlib::Absolutepath] where the home dir is known
- Prefix generated paths explicitly with the home variable
When it happens
Trigger: `purge_ssh_keys => ['.ssh/authorized_keys']` or `=> ['keys/alice']`; Windows paths like 'C:Users\\x' missing a slash; entries built by joining without a leading slash.
Common situations: Shortening paths copied from ~/.ssh documentation; generating keys paths from variables that may be empty (producing '.ssh/...'); forgetting that home-relative entries must start with ~/ or %h/ exactly.
Related errors
- Each entry for purge_ssh_keys must be a string, not a %{klas
- purge_ssh_keys must be true, false, or an array of file name
- Could not find a valid module at %{path}
- Paths must be fully qualified
- Relative paths must not be fully qualified
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/c2cb2caf75701b8f.
Report an issue: GitHub.