redis/redis-rb · error · ArgumentError

ex, px, exat, pxat and persist are mutually exclusive

Error message

ex, px, exat, pxat and persist are mutually exclusive

What it means

Error "ex, px, exat, pxat and persist are mutually exclusive" thrown in redis/redis-rb.

Source

Thrown at lib/redis/commands/strings.rb:120

      #   same typing rules as `lbound`
      # @param [Boolean] saturate cap/floor an out-of-bounds result at the
      #   bound instead of skipping the operation
      # @param [Integer] ex expiration in seconds
      # @param [Integer] px expiration in milliseconds
      # @param [Integer] exat expiration as a Unix timestamp in seconds
      # @param [Integer] pxat expiration as a Unix timestamp in milliseconds
      # @param [Boolean] persist remove the key's expiration
      # @param [Boolean] enx only set the expiration when the key has no TTL
      #   (the increment is applied regardless); requires one of
      #   `ex`/`px`/`exat`/`pxat`
      # @return [Array(Integer, Integer), Array(Float, Float)]
      #   `[new_value, applied_increment]` — Integers in integer mode, Floats
      #   in float mode (under RESP2 and RESP3 alike); `applied_increment`
      #   is 0 when the operation was skipped as out of bounds
      def increx(key, by: nil, lbound: nil, ubound: nil, saturate: nil,
                 ex: nil, px: nil, exat: nil, pxat: nil, persist: nil, enx: nil)
        if [ex, px, exat, pxat, persist].count { |option| option } > 1
          raise ArgumentError, "ex, px, exat, pxat and persist are mutually exclusive"
        end
        raise ArgumentError, "enx is incompatible with persist" if enx && persist
        raise ArgumentError, "enx requires one of ex, px, exat or pxat" if enx && !(ex || px || exat || pxat)

        # The Ruby type of `by` selects the wire mode; anything else would
        # have to silently pick a mode, so it is rejected instead.
        float_mode = case by
        when nil, Integer then false
        when Float then true
        else raise TypeError, "by must be an Integer (BYINT) or a Float (BYFLOAT), got #{by.class}"
        end

        args = [:increx, key]
        args << (float_mode ? "BYFLOAT" : "BYINT") << by if by
        args << "LBOUND" << increx_bound(:lbound, lbound, float_mode) if lbound
        args << "UBOUND" << increx_bound(:ubound, ubound, float_mode) if ubound
        args << "SATURATE" if saturate
        args << "EX" << Integer(ex) if ex

View on GitHub (pinned to 2ba9010b91)

Solutions

  1. Pass only one of ex:, px:, exat:, pxat: or persist: to set the expiry.
  2. Remove the extra expiry options so a single expiration directive remains.

When it happens

Trigger: Thrown at lib/redis/commands/strings.rb:120 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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