{"id":"ca033ae6cf69f45e","repo":"redis/redis-py","slug":"idletimemust-be-an-integer","errorCode":null,"errorMessage":"idletimemust be an integer","messagePattern":"idletimemust be an integer","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":4280,"sourceCode":"        ``idletime`` Used for eviction, this is the number of seconds the\n        key must be idle, prior to execution.\n\n        ``frequency`` Used for eviction, this is the frequency counter of\n        the object stored at the key, prior to execution.\n\n        For more information, see https://redis.io/commands/restore\n        \"\"\"\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 = ...,","sourceCodeStart":4262,"sourceCodeEnd":4298,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L4262-L4298","documentation":"restore() accepts an optional idletime eviction hint that must be an integer (seconds). The code calls int(idletime) inside a try/except ValueError at core.py:2777-2780 and converts it to DataError. Note the message has a missing space ('idletimemust be an integer') but the meaning is clear.","triggerScenarios":"r.restore('k', 0, blob, idletime='abc') or any non-numeric string for idletime. A float like 1.5 would succeed (int() truncates), but non-numeric strings fail.","commonSituations":"Forwarding unparsed config/CLI strings into restore(); deserialized DUMP payloads where idletime came back as a string.","solutions":["Pass an int for idletime, e.g. r.restore('k', 0, blob, idletime=100).","Coerce and validate upstream: idletime = int(idletime) before calling restore().","Omit idletime entirely if you do not need to set an idle eviction hint."],"exampleFix":"# before\nr.restore('k', 0, blob, idletime=user_input)\n\n# after\nr.restore('k', 0, blob, idletime=int(user_input))","handlingStrategy":"validation","validationCode":"if idletime is not None:\n    idletime = int(idletime)  # raises early if non-numeric\nr.restore('k', 0, blob, idletime=idletime)","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, idletime=idletime)\nexcept DataError as e:\n    if 'idletime' in str(e):\n        r.restore('k', 0, blob, idletime=int(idletime))\n    else:\n        raise","preventionTips":["Coerce idletime to int at the config/CLI boundary, not inside the restore call.","Omit idletime when you are not restoring idle-time eviction metadata."],"tags":["redis","restore","validation","type-coercion","eviction"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}