redis/redis-py · error · LockError
Cannot reacquire a lock with no timeout
Error message
Cannot reacquire a lock with no timeout
What it means
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.
Solutions
- Create the lock with a timeout (Lock(r, name, timeout=30)).
- Do not call reacquire on indefinite locks.
Example fix
# before lock = Lock(r, 'resource') # timeout=None default await lock.reacquire() # LockError # after lock = Lock(r, 'resource', timeout=30) await lock.reacquire()
Defensive patterns
Strategy: validation
Validate before calling
if lock.timeout is None:
raise ConfigError('Cannot reacquire a lock without a timeout; create Lock(..., timeout=N)') Prevention
- Construct renewable locks with a timeout.
- Do not call reacquire() on indefinite (manual-release) locks.
When it happens
Trigger: Creating Lock(r, name) with the default timeout=None and then calling lock.reacquire().
Common situations: Indefinite lock used with a renewal/reacquire pattern; missing timeout in lock config.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Cannot extend a lock with no timeout
- Cannot extend a lock that's no longer owned
- Cannot reacquire a lock that's no longer owned
- Cannot release a lock that's no longer owned
- Cannot disable maintenance notifications after enabling them
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/b0ade59d493f5a8e.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/lock.py:334
additional_time = int(additional_time * 1000)
if not bool(
await self.lua_extend(
keys=[self.name],
args=[self.local.token, additional_time, replace_ttl and "1" or "0"],
client=self.redis,
)
):
raise LockNotOwnedError("Cannot extend a lock that's no longer owned")
return True
def reacquire(self) -> Awaitable[Literal[True]]:
"""
Resets a TTL of an already acquired lock back to a timeout value.
"""
if self.local.token is None:
raise LockError("Cannot reacquire an unlocked lock")
if self.timeout is None:
raise LockError("Cannot reacquire a lock with no timeout")
return self.do_reacquire()
async def do_reacquire(self) -> Literal[True]:
timeout = int(self.timeout * 1000)
if not bool(
await self.lua_reacquire(
keys=[self.name], args=[self.local.token, timeout], client=self.redis
)
):
raise LockNotOwnedError("Cannot reacquire a lock that's no longer owned")
return True
View on GitHub (pinned to 6a6b581b48)