redis/redis-rb · error · ArgumentError

logic must be :and or :or

Error message

logic must be :and or :or

What it means

argrep's optional logic: keyword combines the EXACT/MATCH/GLOB/RE predicates. The value is stringified and upcased, then must equal AND or OR; any other truthy value raises ArgumentError 'logic must be :and or :or'. Omitting the keyword (nil) sends no operator and is always safe.

Source

Thrown at lib/redis/commands/arrays.rb:286

      # @param [String, Array<String>] exact match by exact equality
      # @param [String, Array<String>] match match by substring
      # @param [String, Array<String>] glob match by glob-style pattern (`*`, `?`, `[...]`)
      # @param [String, Array<String>] re match by regular expression
      # @param [Symbol] logic `:and` or `:or` — how multiple predicates combine (server default is OR)
      # @param [Integer] limit stop after this many matches
      # @param [Boolean] with_values return `[index, value]` pairs instead of indices
      # @param [Boolean] nocase case-insensitive comparison for all predicates
      # @return [Array<Integer>, Array<Array(Integer, String)>] matching
      #   indices in traversal order, or `[index, value]` pairs with `with_values`
      def argrep(key, start, stop, exact: nil, match: nil, glob: nil, re: nil,
                 logic: nil, limit: nil, with_values: nil, nocase: nil)
        args = [:argrep, key, argrep_bound(start), argrep_bound(stop)]
        { "EXACT" => exact, "MATCH" => match, "GLOB" => glob, "RE" => re }.each do |predicate, values|
          Array(values).each { |value| args << predicate << value }
        end
        if logic
          operator = logic.to_s.upcase
          raise ArgumentError, "logic must be :and or :or" unless %w[AND OR].include?(operator)

          args << operator
        end
        args << "LIMIT" << Integer(limit) if limit
        args << "WITHVALUES" if with_values
        args << "NOCASE" if nocase
        send_command(args)
      end

      # Perform an aggregate operation on the non-empty elements in a range.
      #
      # Supported operations: `:sum`, `:min`, `:max` (numeric, returned as
      # Float), `:and`, `:or`, `:xor` (bitwise, floats truncated toward
      # zero), `:match` (count of elements equal to `value`) and `:used`
      # (count of non-empty elements).
      #
      # @example
      #   redis.arop("foo", 0, 9, :sum)

View on GitHub (pinned to 2ba9010b91)

Solutions

  1. Pass only logic: :and or logic: :or (any case works — to_s.upcase is applied), or omit the keyword entirely
  2. Whitelist user input before the call: accept it only when logic.to_s.downcase is 'and' or 'or', else drop it or raise your own error
  3. Rescue ArgumentError and surface the allowed values to the caller/UI

Example fix

# before
redis.argrep('foo', 0, -1, match: 'a*', logic: :xor)  # ArgumentError

# after
redis.argrep('foo', 0, -1, match: 'a*', logic: :or)
Defensive patterns

Strategy: type-guard

Validate before calling

logic = %w[and or].include?(logic.to_s.downcase) ? logic : nil
redis.argrep(key, start, stop, match: m, logic: logic)

Type guard

def valid_argrep_logic?(value)
  %w[and or].include?(value.to_s.downcase)
end

Try / catch

begin
  redis.argrep(key, start, stop, match: m, logic: logic)
rescue ArgumentError
  retry_allowed = logic = :and  # or surface the allowed values to the caller
  retry
end

Prevention

When it happens

Trigger: redis.argrep('k', 0, -1, match: 'x', logic: :xor); logic: 'NOT'; a variable defaulting to a flag name from another API (e.g. :all) passed straight through.

Common situations: Copy-pasting operator names from set operations or SQL; user-supplied filter parameters forwarded without whitelisting; typos like :nad or 'orr'.

Related errors


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