{"record":{"id":"c1b5ba18f0d97040","repo":"puppetlabs/puppet","slug":"key-value-pairs-must-be-separated-by-separator","errorCode":null,"errorMessage":"Key/value pairs must be separated by '%{separator}'","messagePattern":"Key/value pairs must be separated by '%(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/property/keyvalue.rb","lineNumber":139,"sourceCode":"      def insync?(is)\n        return true unless is\n\n        (is == should)\n      end\n\n      # We only accept an array of key/value pairs (strings), a single\n      # key/value pair (string) or a Hash as valid values for our property.\n      # Note that for an array property value, the 'value' passed into the\n      # block corresponds to the array element.\n      validate do |value|\n        unless value.is_a?(String) || value.is_a?(Hash)\n          raise ArgumentError, _(\"The %{name} property must be specified as a hash or an array of key/value pairs (strings)!\") % { name: name }\n        end\n\n        next if value.is_a?(Hash)\n\n        unless value.include?(separator.to_s)\n          raise ArgumentError, _(\"Key/value pairs must be separated by '%{separator}'\") % { separator: separator }\n        end\n      end\n\n      # The validate step ensures that our passed-in value is\n      # either a String or a Hash. If our value's a string,\n      # then nothing else needs to be done. Otherwise, we need\n      # to stringify the hash's keys and values to match our\n      # internal representation of the property's value.\n      munge do |value|\n        next value if value.is_a?(String)\n\n        munged_value = value.to_a.map! do |hash_key, hash_value|\n          [hash_key.to_s.strip.to_sym, hash_value.to_s]\n        end\n\n        munged_value.to_h\n      end\n    end","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/property/keyvalue.rb#L121-L157","documentation":"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.","triggerScenarios":"attrs => 'justakey' (no '=' anywhere); the property class overrides separator to ':' but the data still uses '='; values produced by join/concat without inserting the separator.","commonSituations":"Separator mismatches between the property class and the data; hand-written Hiera values; plain identifiers supplied where a pair was expected.","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."],"exampleFix":"# before (Puppet DSL)\nmytype { 'x': attrs => 'justakey' }    # ArgumentError: must be separated by '='\n\n# after\nmytype { 'x': attrs => 'justakey=1' }  # or attrs => { 'justakey' => '1' }","handlingStrategy":"validation","validationCode":"sep = '='   # use the property's separator method value\nfail \"missing separator '#{sep}' in #{s}\" unless s.include?(sep)\n\n# Puppet DSL\nunless $s =~ /=/ { fail(\"value '${s}' must be key=value\") }","typeGuard":"def keyvalue_pair?(s, sep = '=')\n  s.is_a?(String) && s.include?(sep)\nend","tryCatchPattern":null,"preventionTips":["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."],"tags":["puppet","property","keyvalue","separator","puppet-dsl"],"backgroundTag":"invalid-key-value-format","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}