{"record":{"id":"79b00ee8bf2de581","repo":"redis/redis-py","slug":"unable-to-acquire-lock-within-the-time-specified","errorCode":null,"errorMessage":"Unable to acquire lock within the time specified","messagePattern":"Unable to acquire lock within the time specified","errorType":"exception","errorClass":"LockError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/lock.py","lineNumber":173,"sourceCode":"        self.local = threading.local() if self.thread_local else SimpleNamespace()\n        self.raise_on_release_error = raise_on_release_error\n        self.local.token = None\n        self.register_scripts()\n\n    def register_scripts(self):\n        cls = self.__class__\n        client = self.redis\n        if cls.lua_release is None:\n            cls.lua_release = client.register_script(cls.LUA_RELEASE_SCRIPT)\n        if cls.lua_extend is None:\n            cls.lua_extend = client.register_script(cls.LUA_EXTEND_SCRIPT)\n        if cls.lua_reacquire is None:\n            cls.lua_reacquire = client.register_script(cls.LUA_REACQUIRE_SCRIPT)\n\n    async def __aenter__(self):\n        if await self.acquire():\n            return self\n        raise LockError(\"Unable to acquire lock within the time specified\")\n\n    async def __aexit__(self, exc_type, exc_value, traceback):\n        try:\n            await self.release()\n        except LockError:\n            if self.raise_on_release_error:\n                raise\n            logger.warning(\n                \"Lock was unlocked or no longer owned when exiting context manager.\"\n            )\n\n    async def acquire(\n        self,\n        blocking: Optional[bool] = None,\n        blocking_timeout: Optional[Number] = None,\n        token: Optional[Union[str, bytes]] = None,\n    ):\n        \"\"\"","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/lock.py#L155-L191","documentation":"When a Lock is used as an async context manager, __aenter__ calls acquire(); if it returns False (the blocking_timeout elapsed without winning the lock), LockError is raised so the 'async with' body never executes. A direct (non-context-manager) acquire() instead returns False, so this error specifically signals context-manager acquisition timeout.","triggerScenarios":"'async with lock:' where contention lasts longer than the lock's blocking_timeout (or default), so acquire() exhausts its retries and returns False inside __aenter__.","commonSituations":"High lock contention; forgotten or delayed release; critical sections longer than expected; blocking_timeout set too low; deadlock.","solutions":["Increase blocking_timeout when constructing the Lock.","Ensure locks are released promptly and the token/thread_local setup is correct.","Catch LockError and degrade gracefully instead of failing the request.","Shorten the critical section protected by the lock."],"exampleFix":"# before\nlock = Lock(r, 'resource', blocking_timeout=1)\nasync with lock:  # raises LockError under contention\n    ...\n# after\nfrom redis.exceptions import LockError\nlock = Lock(r, 'resource', blocking_timeout=30)\ntry:\n    async with lock:\n        ...\nexcept LockError:\n    ...  # handle contention gracefully","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from redis.exceptions import LockError\ntry:\n    async with lock:\n        ...\nexcept LockError:\n    # contention timeout: degrade gracefully\n    ...","preventionTips":["Set blocking_timeout generously relative to expected contention.","Release locks quickly and keep critical sections short.","Catch LockError to fall back instead of failing the caller."],"tags":["lock","timeout","distributed-lock","async"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}