redis/redis-rb · error · ArgumentError
wrong number of arguments (expected key/path/value triplets)
Error message
wrong number of arguments (expected key/path/value triplets)
What it means
JSON.MSET writes several key/path/value triplets in one atomic command, and the Ruby wrapper takes them as a flat splat, so the total argument count must be a positive multiple of 3. An empty call, or a trailing partial triplet, raises ArgumentError before any serialization happens (lib/redis/commands/modules/json.rb:162). Note that redis.json_mset(some_array) passes ONE argument (an Array), which is not divisible by 3 and hits the same raise.
Source
Thrown at lib/redis/commands/modules/json.rb:162
end
# Set one or more JSON values atomically, one per +key+/+path+/+value+ triplet. Either all
# of the writes are applied or none are. For a key that does not yet exist the +path+ must
# be the root ("$").
#
# By default each value is a Ruby object serialized with JSON.generate; pass +raw: true+ to
# send already-encoded JSON strings through untouched.
#
# @example
# redis.json_mset("doc1", "$", { "a" => 1 }, "doc2", "$", { "b" => 2 })
# # => "OK"
#
# @param [Array] args a flat list of key, path, value triplets
# @param [Boolean] raw treat each value as an already-encoded JSON string
# @return [String] the raw "OK" reply
# @raise [ArgumentError] unless +args+ is a non-empty list of complete triplets
def json_mset(*args, raw: false)
raise ArgumentError, "wrong number of arguments (expected key/path/value triplets)" \
if args.empty? || !(args.size % 3).zero?
command = [:"JSON.MSET"]
args.each_slice(3) do |key, path, value|
command << key << path << (raw ? value : ::JSON.generate(value))
end
send_command(command)
end
# Get the values at a single +path+ from one or more +keys+.
#
# Returns one element per key, in order, parsed from JSON text into a Ruby object (or nil
# when the key or path does not exist). Pass +raw: true+ to get the unparsed JSON strings.
#
# @example
# redis.json_mget("doc1", "doc2", "$.a")
# # => [[1], [2]]
#View on GitHub (pinned to 2ba9010b91)
Solutions
- Splat the list: redis.json_mset(*triplets)
- Validate !triplets.empty? && triplets.size % 3 == 0 before calling
- When building triplets in a loop, append key, path and value together so a partial triplet cannot be produced
Example fix
// before redis.json_mset(triplets) // after redis.json_mset(*triplets)
Defensive patterns
Strategy: validation
Validate before calling
def json_mset_bulk(redis, *triplets) raise ArgumentError, "expected key/path/value triplets" if triplets.empty? || triplets.size % 3 != 0 redis.json_mset(*triplets) end
Type guard
triplets.is_a?(Array) && !triplets.empty? && (triplets.size % 3).zero?
Try / catch
begin
redis.json_mset(*triplets)
rescue ArgumentError => e
raise BatchError, "triplet list malformed: #{e.message}"
end Prevention
- Splat arrays into json_mset, never pass the array itself
- Keep triplets as [key, path, value] rows so the structure is checkable before flattening
- Unit-test the triplet builder with odd-length inputs
When it happens
Trigger: redis.json_mset() with no args; redis.json_mset("doc", "$") with only 2 args; a dynamically built list of 7 elements whose last triplet lost its value; redis.json_mset(triplets) where triplets is an Array that was never splatted.
Common situations: Forgetting the splat when the triplets live in an array; looping with each_slice(3) over an odd-length list and pushing a partial tail; refactoring several json_set calls into one batched mset and miscounting arguments.
Related errors
- nx and xx are mutually exclusive
- fpha accepts only: #{JSON_SET_FPHA_TYPES.join(', ')}
- index requires a path
- wrong number of arguments
- collect fields must be :all or a non-empty list
AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23).
Data as JSON: /api/errors/ef7833ab53c1ced6.
Report an issue: GitHub.