puppetlabs/puppet · error · ArgumentError
Each entry for purge_ssh_keys must be a string, not a %{klas
Error message
Each entry for purge_ssh_keys must be a string, not a %{klass} What it means
Raised by the validate block of the `purge_ssh_keys` property on the `user` type. After allowing the true/false symbols, the value (a bare String is wrapped into a one-element array) must be an Array whose every entry is_a?(String); any non-String entry (Integer, nil, hash) raises this with the entry's class interpolated. Each string entry is then also required to be an absolute path or start with ~/ or %h/ (see the companion path error).
Source
Thrown at lib/puppet/type/user.rb:743
* An array of file paths --- look for keys in all of the files listed. Purge
any keys that aren't managed as `ssh_authorized_key` resources. If any of
these paths starts with `~` or `%h`, that token will be replaced with
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"] : []View on GitHub (pinned to e227c27540)
Solutions
- Ensure every entry is a string: `purge_ssh_keys => ['/etc/ssh/keys/alice/authorized_keys']`
- Quote numeric-looking path components in YAML/Hiera
- Map/clean the list in the profile: $keys.map |$k| { String($k) } before passing
Example fix
# before
user { 'alice':
ensure => present,
purge_ssh_keys => [12345],
}
# after
user { 'alice':
ensure => present,
purge_ssh_keys => ['/etc/ssh/keys/alice/authorized_keys'],
} Defensive patterns
Strategy: validation
Validate before calling
keys = [raw].flatten.compact
raise TypeError, 'purge_ssh_keys entries must be strings' unless keys.all? { |k| k.is_a?(String) }
keys = keys.map(&:to_s) rescue nil Type guard
def valid_purge_keys?(v)
return true if [true, false].include?(v)
v.is_a?(Array) && v.all? { |e| e.is_a?(String) }
end Prevention
- Quote all Hiera entries that could parse as YAML numbers
- Type profile params as Variant[Boolean, Array[String]]
- Run `puppet lookup --explain` to confirm data types at the boundary
When it happens
Trigger: `user { 'alice': purge_ssh_keys => [12345] }`, `=> [nil]`, `=> [{'path' => 'x'}]`; Hiera data mixing types; YAML unquoted values parsed as integers (e.g. a path like 2024).
Common situations: YAML bare tokens that parse as numbers; lookup() results merged from heterogeneous sources; programmatic generation of key lists that includes integers or nils.
Related errors
- Password warning days must be provided as a number.
- Group names must be provided, not GID numbers.
- Role names must be provided, not numbers
- Auth names must be provided, not numbers
- Profile names must be provided, not numbers
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/235c14ce124928cb.
Report an issue: GitHub.