redis/redis-rb · error · ArgumentError

index requires a path

Error message

index requires a path

What it means

json_arrpop takes positional optional path then optional index, mirroring the wire form JSON.ARRPOP key [path [index]]. An index is only meaningful relative to a path, and because the parameters are positional, an index with a nil path would be silently mis-bound (the index would travel where the server expects a path). The wrapper therefore raises ArgumentError when index is given without path (lib/redis/commands/modules/json.rb:366).

Source

Thrown at lib/redis/commands/modules/json.rb:366

      # Remove and return an element from the array at +path+. When +path+ is omitted it defaults
      # to the root; when +index+ is omitted it defaults to -1 (the last element).
      #
      # The popped element is returned as parsed JSON (a Ruby object), or as the unparsed JSON
      # string when +raw: true+.
      #
      # @example
      #   redis.json_arrpop("doc", "$.colors", 0)
      #     # => ["black"]
      #
      # @param [String] key
      # @param [String] path an optional JSONPath to the target array (defaults to the root "$")
      # @param [Integer] index an optional position to pop from (defaults to -1, the last element)
      # @param [Boolean] raw return the unparsed JSON string(s) instead of parsed Ruby objects
      # @return [Array, Object, nil] the popped value(s); an Array for a JSONPath, a single value
      #   for a legacy path, nil for an empty array or a non-array match
      # @raise [ArgumentError] if +index+ is given without a +path+
      def json_arrpop(key, path = nil, index = nil, raw: false)
        raise ArgumentError, "index requires a path" if !index.nil? && path.nil?

        args = [:"JSON.ARRPOP", key]
        if path
          args << path
          args << Integer(index) unless index.nil?
        end

        send_command(args) do |reply|
          if reply.nil? || raw
            reply
          elsif reply.is_a?(Array)
            reply.map { |value| value.nil? ? nil : ::JSON.parse(value) }
          else
            ::JSON.parse(reply)
          end
        end
      end

View on GitHub (pinned to 2ba9010b91)

Solutions

  1. Always pass the path when using an index: redis.json_arrpop("doc", "$", 0)
  2. For the common pop-last case, omit both: redis.json_arrpop("doc")
  3. Wrap the call in a keyword-based helper (path:, index:) to remove the positional trap

Example fix

// before
redis.json_arrpop("doc", 0)
// after
redis.json_arrpop("doc", "$", 0)
Defensive patterns

Strategy: validation

Validate before calling

def arrpop(redis, key, path: "$", index: nil)
  raise ArgumentError, "index requires a path" if index && path.nil?
  index ? redis.json_arrpop(key, path, index) : redis.json_arrpop(key, path)
end

Type guard

index.nil? || !path.nil?

Try / catch

begin
  redis.json_arrpop(key, path, index)
rescue ArgumentError => e
  raise UsageError, e.message
end

Prevention

When it happens

Trigger: redis.json_arrpop("doc", 0) when trying to pop the first element of the root array, because 0 lands in the path slot; redis.json_arrpop("doc", nil, -1) with an explicit nil path.

Common situations: Assuming the root array is implied the way it is in json_get; porting RedisJSON CLI examples that always show the $ path explicitly; wanting index 0 (the first element) and forgetting the "$" argument.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23). Data as JSON: /api/errors/a0cc353e4f42d9a1. Report an issue: GitHub.