{"record":{"id":"b0ade59d493f5a8e","repo":"redis/redis-py","slug":"cannot-reacquire-a-lock-with-no-timeout","errorCode":null,"errorMessage":"Cannot reacquire a lock with no timeout","messagePattern":"Cannot reacquire a lock with no timeout","errorType":"exception","errorClass":"LockError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/lock.py","lineNumber":334,"sourceCode":"        additional_time = int(additional_time * 1000)\n        if not bool(\n            await self.lua_extend(\n                keys=[self.name],\n                args=[self.local.token, additional_time, replace_ttl and \"1\" or \"0\"],\n                client=self.redis,\n            )\n        ):\n            raise LockNotOwnedError(\"Cannot extend a lock that's no longer owned\")\n        return True\n\n    def reacquire(self) -> Awaitable[Literal[True]]:\n        \"\"\"\n        Resets a TTL of an already acquired lock back to a timeout value.\n        \"\"\"\n        if self.local.token is None:\n            raise LockError(\"Cannot reacquire an unlocked lock\")\n        if self.timeout is None:\n            raise LockError(\"Cannot reacquire a lock with no timeout\")\n        return self.do_reacquire()\n\n    async def do_reacquire(self) -> Literal[True]:\n        timeout = int(self.timeout * 1000)\n        if not bool(\n            await self.lua_reacquire(\n                keys=[self.name], args=[self.local.token, timeout], client=self.redis\n            )\n        ):\n            raise LockNotOwnedError(\"Cannot reacquire a lock that's no longer owned\")\n        return True\n","sourceCodeStart":316,"sourceCodeEnd":346,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/lock.py#L316-L346","documentation":"reacquire() restores the lock's original timeout; a Lock created with timeout=None has no TTL to restore, so the client rejects reacquire() with LockError. Identical rationale to error 135 but on the reacquire path.","triggerScenarios":"Creating Lock(r, name) with the default timeout=None and then calling lock.reacquire().","commonSituations":"Indefinite lock used with a renewal/reacquire pattern; missing timeout in lock config.","solutions":["Create the lock with a timeout (Lock(r, name, timeout=30)).","Do not call reacquire on indefinite locks."],"exampleFix":"# before\nlock = Lock(r, 'resource')  # timeout=None default\nawait lock.reacquire()  # LockError\n# after\nlock = Lock(r, 'resource', timeout=30)\nawait lock.reacquire()","handlingStrategy":"validation","validationCode":"if lock.timeout is None:\n    raise ConfigError('Cannot reacquire a lock without a timeout; create Lock(..., timeout=N)')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Construct renewable locks with a timeout.","Do not call reacquire() on indefinite (manual-release) locks."],"tags":["lock","ttl","config","async"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}