{"id":"9fd087ef42ff397b","repo":"redis/redis-py","slug":"byfloat-and-byint-are-mutually-exclusive","errorCode":null,"errorMessage":"``byfloat`` and ``byint`` are mutually exclusive.","messagePattern":"``byfloat`` and ``byint`` are mutually exclusive\\.","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":3484,"sourceCode":"\n        ``lbound`` and ``ubound`` constrain the valid range of the result.\n\n        If ``saturate`` is True, out-of-bounds results are saturated to the\n        specified bound, or to the type limit when no bound is specified.\n        Otherwise, out-of-bounds results are rejected, leaving the value and\n        TTL unchanged and returning the current value and zero as the actual\n        increment.\n\n        ``enx`` applies the expiration only when the key does not already\n        have an expiration, and requires ``ex``, ``px``, ``exat``, or ``pxat``.\n        \"\"\"\n        if not at_most_one_value_set(\n            (\n                byfloat is not None,\n                byint is not None,\n            )\n        ):\n            raise DataError(\"``byfloat`` and ``byint`` are mutually exclusive.\")\n\n        if not at_most_one_value_set(\n            (\n                ex is not None,\n                px is not None,\n                exat is not None,\n                pxat is not None,\n                persist,\n            )\n        ):\n            raise DataError(\n                \"``ex``, ``px``, ``exat``, ``pxat``, \"\n                \"and ``persist`` are mutually exclusive.\"\n            )\n\n        if enx and ex is None and px is None and exat is None and pxat is None:\n            raise DataError(\n                \"``enx`` requires one of ``ex``, ``px``, ``exat``, or ``pxat``.\"","sourceCodeStart":3466,"sourceCodeEnd":3502,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L3466-L3502","documentation":"increx() (experimental) increments a value by either a float (BYFLOAT) or an int (BYINT); the two are mutually exclusive because they select different Redis increment modes. The at_most_one_value_set guard at core.py:3478 raises DataError if both are set.","triggerScenarios":"r.increx('counter', byfloat=1.5, byint=2), or forwarding both from optional kwargs. If neither is set the value increments by one (the default).","commonSituations":"Generic increment helper that accepts both an int and float path; misunderstanding the API as additive; copy-paste from incrby/incrbyfloat which are separate commands.","solutions":["Pass exactly one of byfloat or byint depending on the value type, e.g. r.increx('counter', byint=5).","Omit both to increment by one.","In a helper, branch on isinstance(value, float) vs int and pass the correct single kwarg."],"exampleFix":"# before\nr.increx('counter', byfloat=1.5, byint=2)\n\n# after\nr.increx('counter', byfloat=1.5)  # choose one","handlingStrategy":"validation","validationCode":"if byfloat is not None and byint is not None:\n    raise ValueError('increx: pass byfloat or byint, not both')\nr.increx('k', byfloat=byfloat, byint=byint)","typeGuard":"def valid_increx_amount(byfloat, byint) -> bool:\n    return not (byfloat is not None and byint is not None)","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    r.increx('k', byfloat=byfloat, byint=byint)\nexcept DataError as e:\n    if 'byfloat and byint' in str(e):\n        r.increx('k', byint=byint)  # keep one\n    else:\n        raise","preventionTips":["Branch on value type in your helper and pass exactly one of byfloat/byint.","Omit both for a default +1 increment."],"tags":["redis","increx","validation","parameter-conflict","experimental"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}