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

  1. Create the lock with a timeout (Lock(r, name, timeout=30)).
  2. 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

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

Related errors


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)