{"record":{"id":"e926ed6c14773cd9","repo":"redis/redis-rb","slug":"ex-px-exat-pxat-and-persist-are-mutually-exclus","errorCode":null,"errorMessage":"ex, px, exat, pxat and persist are mutually exclusive","messagePattern":"ex, px, exat, pxat and persist are mutually exclusive","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/redis/commands/strings.rb","lineNumber":120,"sourceCode":"      #   same typing rules as `lbound`\n      # @param [Boolean] saturate cap/floor an out-of-bounds result at the\n      #   bound instead of skipping the operation\n      # @param [Integer] ex expiration in seconds\n      # @param [Integer] px expiration in milliseconds\n      # @param [Integer] exat expiration as a Unix timestamp in seconds\n      # @param [Integer] pxat expiration as a Unix timestamp in milliseconds\n      # @param [Boolean] persist remove the key's expiration\n      # @param [Boolean] enx only set the expiration when the key has no TTL\n      #   (the increment is applied regardless); requires one of\n      #   `ex`/`px`/`exat`/`pxat`\n      # @return [Array(Integer, Integer), Array(Float, Float)]\n      #   `[new_value, applied_increment]` — Integers in integer mode, Floats\n      #   in float mode (under RESP2 and RESP3 alike); `applied_increment`\n      #   is 0 when the operation was skipped as out of bounds\n      def increx(key, by: nil, lbound: nil, ubound: nil, saturate: nil,\n                 ex: nil, px: nil, exat: nil, pxat: nil, persist: nil, enx: nil)\n        if [ex, px, exat, pxat, persist].count { |option| option } > 1\n          raise ArgumentError, \"ex, px, exat, pxat and persist are mutually exclusive\"\n        end\n        raise ArgumentError, \"enx is incompatible with persist\" if enx && persist\n        raise ArgumentError, \"enx requires one of ex, px, exat or pxat\" if enx && !(ex || px || exat || pxat)\n\n        # The Ruby type of `by` selects the wire mode; anything else would\n        # have to silently pick a mode, so it is rejected instead.\n        float_mode = case by\n        when nil, Integer then false\n        when Float then true\n        else raise TypeError, \"by must be an Integer (BYINT) or a Float (BYFLOAT), got #{by.class}\"\n        end\n\n        args = [:increx, key]\n        args << (float_mode ? \"BYFLOAT\" : \"BYINT\") << by if by\n        args << \"LBOUND\" << increx_bound(:lbound, lbound, float_mode) if lbound\n        args << \"UBOUND\" << increx_bound(:ubound, ubound, float_mode) if ubound\n        args << \"SATURATE\" if saturate\n        args << \"EX\" << Integer(ex) if ex","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/redis/redis-rb/blob/2ba9010b91dab9e0fde1fbae3a9aae003f8bc307/lib/redis/commands/strings.rb#L102-L138","documentation":"Error \"ex, px, exat, pxat and persist are mutually exclusive\" thrown in redis/redis-rb.","triggerScenarios":"Thrown at lib/redis/commands/strings.rb:120 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Pass only one of ex:, px:, exat:, pxat: or persist: to set the expiry.","Remove the extra expiry options so a single expiration directive remains."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"2ba9010b91dab9e0fde1fbae3a9aae003f8bc307","analyzedAt":"2026-08-23T03:54:57.017Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}