bblimke/webmock · error · TypeError
Can't convert #{new_query_values.class} into Hash.
Error message
Can't convert #{new_query_values.class} into Hash. What it means
values_to_query serializes a Hash, an Array of [key, value] pairs, or anything responding to to_hash back into a query string; TypeError is raised for anything else (String, Integer, arbitrary object). nil is a documented short-circuit (returns nil), but an already-serialized query string is NOT accepted - this method is the inverse of query_to_values.
Source
Thrown at lib/webmock/util/query_mapper.rb:185
else
current_node[last_key] = value
end
end
end
##
# Sets the query component for this URI from a Hash object.
# This method produces a query string using the :subscript notation.
# An empty Hash will result in a nil query.
#
# @param [Hash, #to_hash, Array] new_query_values The new query values.
def values_to_query(new_query_values, options = {})
options[:notation] ||= :subscript
return if new_query_values.nil?
unless new_query_values.is_a?(Array)
unless new_query_values.respond_to?(:to_hash)
raise TypeError,
"Can't convert #{new_query_values.class} into Hash."
end
new_query_values = new_query_values.to_hash
new_query_values = new_query_values.inject([]) do |object, (key, value)|
key = key.to_s if key.is_a?(::Symbol) || key.nil?
if value.is_a?(Array) && value.empty?
object << [key.to_s + '[]']
elsif value.is_a?(Array)
value.each { |v| object << [key.to_s + '[]', v] }
elsif value.is_a?(Hash)
value.each { |k, v| object << ["#{key.to_s}[#{k}]", v]}
else
object << [key.to_s, value]
end
object
end
# Useful default for OAuth and caching.
# Only to be used for non-Array inputs. Arrays should preserve order.View on GitHub (pinned to b187df8827)
Solutions
- Pass a Hash ({ 'a' => '1', 'b' => '2' }) or an Array of [key, value] pairs
- If you already have a query string, parse it first with query_to_values and pass the resulting Hash
- Call .to_h on duck-typed objects at the boundary before handing them over
Example fix
// before
query = WebMock::Util::QueryMapper.values_to_query('a=1&b=2')
# => TypeError: Can't convert String into Hash.
// after
query = WebMock::Util::QueryMapper.values_to_query({ 'a' => '1', 'b' => '2' })
# => a=1&b=2 Defensive patterns
Strategy: type-guard
Validate before calling
values = { 'a' => '1', 'b' => '2' } # a Hash, not the string 'a=1&b=2'
raise TypeError, 'values_to_query expects a Hash or Array of pairs' unless values.is_a?(Hash)
query = WebMock::Util::QueryMapper.values_to_query(values) Type guard
def query_values_input?(value) value.is_a?(Hash) || value.is_a?(Array) || value.respond_to?(:to_hash) end
Prevention
- Remember the direction: query_to_values parses strings, values_to_query serializes Hashes
- Convert duck-typed objects with to_h at the boundary
- Never feed a serialized query string back into values_to_query
When it happens
Trigger: WebMock::Util::QueryMapper.values_to_query('a=1&b=2') (passing a query string where a Hash is required); passing an Integer, Symbol, or a Struct/Data object that lacks to_hash; adapters or helpers feeding serialized strings from config into the mapper during add_query_params or build_request_signature.
Common situations: Role confusion between query_to_values (parses strings) and values_to_query (serializes hashes); params round-tripped through JSON ending up as Strings; query strings received from one API handed straight to the mapper to re-serialize.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Invalid notation. Must be one of: [:flat, :dot, :subscript,
- Key was repeated: #{key.inspect}
- Real HTTP connections are disabled. Unregistered request: #{
- #with method invoked with no arguments. Either options hash
- The basic_auth option value should be an array which contain
AI-assisted analysis of bblimke/webmock@b187df8827 (2026-08-23).
Data as JSON: /api/errors/b270593164a196ee.
Report an issue: GitHub.