{"id":"551761017d40cefa","repo":"redis/redis-py","slug":"frequency-must-be-an-integer","errorCode":null,"errorMessage":"frequency must be an integer","messagePattern":"frequency must be an integer","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":4287,"sourceCode":"        \"\"\"\n        params = [name, ttl, value]\n        if replace:\n            params.append(\"REPLACE\")\n        if absttl:\n            params.append(\"ABSTTL\")\n        if idletime is not None:\n            params.append(\"IDLETIME\")\n            try:\n                params.append(int(idletime))\n            except ValueError:\n                raise DataError(\"idletimemust be an integer\")\n\n        if frequency is not None:\n            params.append(\"FREQ\")\n            try:\n                params.append(int(frequency))\n            except ValueError:\n                raise DataError(\"frequency must be an integer\")\n\n        return self.execute_command(\"RESTORE\", *params)\n\n    @overload\n    def set(\n        self: SyncClientProtocol,\n        name: KeyT,\n        value: EncodableT,\n        ex: ExpiryT | None = ...,\n        px: ExpiryT | None = ...,\n        nx: bool = ...,\n        xx: bool = ...,\n        keepttl: bool = ...,\n        get: bool = ...,\n        exat: AbsExpiryT | None = ...,\n        pxat: AbsExpiryT | None = ...,\n        ifeq: bytes | str | None = ...,\n        ifne: bytes | str | None = ...,","sourceCodeStart":4269,"sourceCodeEnd":4305,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L4269-L4305","documentation":"restore() accepts an optional frequency eviction hint (LFU frequency counter) that must be an integer. The code calls int(frequency) in a try/except ValueError at core.py:2784-2787 and re-raises as DataError. Unlike the idletime message, this message is correctly spaced.","triggerScenarios":"r.restore('k', 0, blob, frequency='abc') or any non-numeric string for frequency. Numeric strings like '5' coerce fine.","commonSituations":"Passing a deserialized/CLI frequency value as a string; LFU migration tooling that reads frequency from an exported format.","solutions":["Pass an int for frequency, e.g. r.restore('k', 0, blob, frequency=5).","Coerce upstream: frequency = int(frequency) before the call.","Omit frequency if you are not restoring LFU metadata."],"exampleFix":"# before\nr.restore('k', 0, blob, frequency=freq_str)\n\n# after\nr.restore('k', 0, blob, frequency=int(freq_str))","handlingStrategy":"validation","validationCode":"if frequency is not None:\n    frequency = int(frequency)  # raises early if non-numeric\nr.restore('k', 0, blob, frequency=frequency)","typeGuard":"def is_int_like(v) -> bool:\n    try:\n        int(v)\n        return True\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    r.restore('k', 0, blob, frequency=frequency)\nexcept DataError as e:\n    if 'frequency' in str(e):\n        r.restore('k', 0, blob, frequency=int(frequency))\n    else:\n        raise","preventionTips":["Parse frequency to int upstream when importing LFU metadata.","Omit frequency unless you are intentionally restoring LFU eviction counters."],"tags":["redis","restore","validation","type-coercion","eviction"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}