{"record":{"id":"2af37f30ed213d6d","repo":"puppetlabs/puppet","slug":"http-rest-queries-cannot-handle-values-of-type","errorCode":null,"errorMessage":"HTTP REST queries cannot handle values of type '%{klass}'","messagePattern":"HTTP REST queries cannot handle values of type '%(.+?)'","errorType":"exception","errorClass":"Puppet::HTTP::SerializationError","httpStatus":null,"severity":"error","filePath":"lib/puppet/http/client.rb","lineNumber":447,"sourceCode":"                         value.collect { |val| [key, val] }\n                       else\n                         [key_value]\n                       end\n\n      params.concat(expand_primitive_types_into_parameters(expanded_value))\n    end\n  end\n\n  def expand_primitive_types_into_parameters(data)\n    data.inject([]) do |params, key_value|\n      key, value = key_value\n      case value\n      when nil\n        params\n      when true, false, String, Symbol, Integer, Float\n        params << [key, value]\n      else\n        raise Puppet::HTTP::SerializationError, _(\"HTTP REST queries cannot handle values of type '%{klass}'\") % { klass: value.class }\n      end\n    end\n  end\n\n  def encode_params(params)\n    params = expand_into_parameters(params)\n    params.map do |key, value|\n      \"#{key}=#{Puppet::Util.uri_query_encode(value.to_s)}\"\n    end.join('&')\n  end\n\n  def elapsed(start)\n    (Time.now - start).to_f.round(3)\n  end\n\n  def raise_error(message, cause, connected)\n    if connected\n      raise Puppet::HTTP::HTTPError.new(message, cause)","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/http/client.rb#L429-L465","documentation":"When Puppet::HTTP::Client encodes URL query parameters, arrays at the top level are expanded into repeated keys, but every leaf value must be nil, true/false, String, Symbol, Integer, or Float (client.rb:444). Any other class — Hash, Time, Date, Struct — raises Puppet::HTTP::SerializationError naming the class. Note nested Hashes are not expanded: a hash value goes straight to the primitive check.","triggerScenarios":"client.get(url, params: { since: Time.now }); params: { filter: { kind: 'apply' } } (Hash value); params: { tags: [{ a: 1 }] } (hash inside an array); passing OpenStruct/Struct/BigDecimal objects from fact or report data.","commonSituations":"Query endpoints with timestamp filters where a Time object feels natural; structured filter hashes that the developer expects to be JSON-encoded; data flowing from YAML config where dates auto-parse into Date objects.","solutions":["Convert values to primitives yourself: since: Time.now.utc.iso8601.","Flatten or serialize structured filters into strings before the call (e.g. JSON in a single param if the endpoint accepts it).","For fully custom query strings, encode them into the URL yourself and pass params: {}."],"exampleFix":"# before\nclient.get(url, params: { since: Time.now, environment: 'production' })\n\n# after\nclient.get(url, params: { since: Time.now.utc.iso8601, environment: 'production' })","handlingStrategy":"type-guard","validationCode":"params = params.transform_values { |v| case v when nil, true, false, String, Symbol, Integer, Float then v else v.to_s end }\nclient.get(url, params: params)","typeGuard":"PRIMITIVES = [NilClass, TrueClass, FalseClass, String, Symbol, Integer, Float].freeze\nparam_safe = ->(v) { v.nil? || PRIMITIVES.any? { |c| v.is_a?(c) } }\nparams.each { |k, v| raise ArgumentError, \"#{k} is not URL-encodable\" unless param_safe.call(v) }","tryCatchPattern":"begin\n  client.get(url, params: params)\nrescue Puppet::HTTP::SerializationError => e\n  retry_with = params.transform_values(&:to_s)\n  client.get(url, params: retry_with)\nend","preventionTips":["Convert Time/Date values to iso8601 strings before passing as params.","Do not pass nested Hashes as query params — flatten or JSON-encode them into a single param."],"tags":["puppet","http","query-params","serialization","rest"],"backgroundTag":"unsupported-query-parameter-type","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}