puppetlabs/puppet · error · ArgumentError
Key/value pairs must be separated by '%{separator}'
Error message
Key/value pairs must be separated by '%{separator}' What it means
For KeyValue properties, a String should-value must contain the property's separator ('=' by default; the class-level separator method can be overridden) so it can later be split into key and value (hashify_should calls split(separator)). A string without the separator raises ArgumentError naming the expected one. The check uses include?, so containing the character anywhere passes validation - but parsing still misbehaves if it is not between key and value.
Source
Thrown at lib/puppet/property/keyvalue.rb:139
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|
[hash_key.to_s.strip.to_sym, hash_value.to_s]
end
munged_value.to_h
end
endView on GitHub (pinned to e227c27540)
Solutions
- Format values as key<separator>value matching the property's separator (default '=').
- If the separator is customizable, align the property class and the data.
- Pass a Hash instead of strings to sidestep separator handling entirely.
Example fix
# before (Puppet DSL)
mytype { 'x': attrs => 'justakey' } # ArgumentError: must be separated by '='
# after
mytype { 'x': attrs => 'justakey=1' } # or attrs => { 'justakey' => '1' } Defensive patterns
Strategy: validation
Validate before calling
sep = '=' # use the property's separator method value
fail "missing separator '#{sep}' in #{s}" unless s.include?(sep)
# Puppet DSL
unless $s =~ /=/ { fail("value '${s}' must be key=value") } Type guard
def keyvalue_pair?(s, sep = '=') s.is_a?(String) && s.include?(sep) end
Prevention
- Always author key/value data as '<key>=<value>' matching the property's separator.
- Prefer Hash input when the property accepts it - there is no separator to get wrong.
- If a property overrides the separator, document it next to the parameter.
When it happens
Trigger: attrs => 'justakey' (no '=' anywhere); the property class overrides separator to ':' but the data still uses '='; values produced by join/concat without inserting the separator.
Common situations: Separator mismatches between the property class and the data; hand-written Hiera values; plain identifiers supplied where a pair was expected.
Related errors
- The %{name} property must be specified as a hash or an array
- odd number of arguments for Hash
- Type alias '#{name}' cannot be resolved to a real type
- Could not convert change '%{name}' to string: %{detail}
- Invalid value %{value}: %{property} must be an Integer!
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/c1b5ba18f0d97040.
Report an issue: GitHub.