puppetlabs/puppet · error · ArgumentError
The %{name} property must be specified as a hash or an array
Error message
The %{name} property must be specified as a hash or an array of key/value pairs (strings)! What it means
Puppet::Property::KeyValue is a base class for properties holding key/value settings (strings like 'k=v' or a Hash). Its validate block accepts only a String or a Hash; any other object - Integer, Array of non-strings, nil - raises ArgumentError demanding 'a hash or an array of key/value pairs (strings)'. Puppet casts should-values to arrays, so the block runs per element: one bad element fails the whole property value.
Source
Thrown at lib/puppet/property/keyvalue.rb:133
:absent
end
end
# Returns true if there is no _is_ value, else returns if _is_ is equal to _should_ using == as comparison.
# @return [Boolean] whether the property is in sync or not.
def insync?(is)
return true unless is
(is == should)
end
# We only accept an array of key/value pairs (strings), a single
# key/value pair (string) or a Hash as valid values for our property.
# Note that for an array property value, the 'value' passed into the
# block corresponds to the array element.
validate do |value|
unless value.is_a?(String) || value.is_a?(Hash)
raise ArgumentError, _("The %{name} property must be specified as a hash or an array of key/value pairs (strings)!") % { name: name }
end
next if value.is_a?(Hash)
unless value.include?(separator.to_s)
raise ArgumentError, _("Key/value pairs must be separated by '%{separator}'") % { separator: separator }
end
end
# The validate step ensures that our passed-in value is
# either a String or a Hash. If our value's a string,
# then nothing else needs to be done. Otherwise, we need
# to stringify the hash's keys and values to match our
# internal representation of the property's value.
munge do |value|
next value if value.is_a?(String)
munged_value = value.to_a.map! do |hash_key, hash_value|View on GitHub (pinned to e227c27540)
Solutions
- Pass strings formatted as key<separator>value: attrs => 'answer=42'.
- Pass a single Hash when the property supports it: attrs => { 'answer' => '42' }.
- Validate and coerce the parameter before it reaches the resource.
Example fix
# before (Puppet DSL)
mytype { 'x': attrs => 42 } # ArgumentError
# after
mytype { 'x': attrs => 'answer=42' } # or attrs => { 'answer' => '42' } Defensive patterns
Strategy: validation
Validate before calling
# Ruby
ok = value.is_a?(String) || value.is_a?(Hash)
# Puppet DSL: constrain the parameter
Variant[String, Hash] $attrs = {} Type guard
def keyvalue_shaped?(v) v.is_a?(String) || v.is_a?(Hash) end
Prevention
- Type module parameters as Variant[String, Hash] (or an Array of them) so bad shapes fail at compile time.
- Keep numeric values inside the pair string ('answer=42'), not as bare numbers.
- Remember validation runs per element for array values - check every element.
When it happens
Trigger: Setting a KeyValue-derived property to a number (attrs => 42), an array of numbers, or undef; passing nested structures where flat 'k=v' strings or a single Hash were expected.
Common situations: Hiera data storing numbers without quotes (or over-quoted strings); users assuming structured input; modules whose documentation is unclear about the accepted shape.
Related errors
- Key/value pairs must be separated by '%{separator}'
- One or more file(s) specified did not exist: %{files}
- a data type must have an interface
- Resource instance does not match request key
- Instance name %{name} does not match requested key %{key}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/8479157baa36e7dc.
Report an issue: GitHub.