redis/redis-py · error · RedisError
SHUTDOWN seems to have failed.
Error message
SHUTDOWN seems to have failed.
What it means
Raised by shutdown() (redis/commands/core.py:2129) after the SHUTDOWN command returns WITHOUT raising a ConnectionError. The expected success path is that the server closes the connection during shutdown, surfacing as a ConnectionError that the method swallows and returns normally; if execute_command returns at all, the library assumes the server is still alive and raises a redis.exceptions.RedisError. This typically happens with SHUTDOWN ABORT (which cancels an in-progress shutdown and returns OK), with certain NOW/FORCE combinations, or when a replica/ACL guard prevents the shutdown.
Solutions
- If you intended to abort, wrap the call: try: r.shutdown(abort=True) except RedisError: pass
- Verify the user has the admin/shutdown ACL permission before calling
- For a real shutdown, ensure no abort flag and that the target is a writable master; expect ConnectionError as the normal outcome
- Check server logs / replica lag if shutdown is being blocked by min-replicas configuration
Example fix
# before
r.shutdown(abort=True) # raises RedisError because server replied OK
# after
from redis.exceptions import RedisError
try:
r.shutdown(abort=True)
except RedisError:
pass # abort returns a reply rather than closing the connection Defensive patterns
Strategy: try-catch
Validate before calling
# Pre-check ACL for shutdown permission when feasible
me = r.execute_command("ACL", "WHOAMI")
# also detect abort mode, which legitimately returns a reply
if abort:
# SHUTDOWN ABORT returns OK instead of closing the connection
expected_reply = True Try / catch
from redis.exceptions import RedisError, ConnectionError
try:
r.shutdown(save=save, nosave=nosave, abort=abort)
except ConnectionError:
pass # normal: server closed the connection during shutdown
except RedisError as e:
if "SHUTDOWN seems to have failed" in str(e):
# server replied instead of closing (e.g. SHUTDOWN ABORT) - inspect logs
pass
else:
raise Prevention
- Expect ConnectionError as the SUCCESS path for a real shutdown.
- Wrap abort=True calls because the server returns OK rather than closing the link.
- Verify the user has the +shutdown ACL flag and the node is a writable master.
- Check min-replicas config if shutdown appears to be blocked.
When it happens
Trigger: Calling r.shutdown(abort=True) (server returns OK instead of closing the link); calling shutdown against a node protected by min-replicas/ACL that rejects the operation; or a Redis version whose shutdown path returns a reply rather than dropping the connection.
Common situations: Using abort=True to cancel a shutdown in failover tests; running shutdown against a managed/Redis Cloud endpoint that intercepts it; the connection being proxied so the close is masked.
Related errors
- SHUTDOWN save and nosave cannot both be set
- Scheduler is stopped
- Timed out closing connection after
- Too many connections
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/b088730f62001e01.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/core.py:2129
if save and nosave:
raise DataError("SHUTDOWN save and nosave cannot both be set")
args = ["SHUTDOWN"]
if save:
args.append("SAVE")
if nosave:
args.append("NOSAVE")
if now:
args.append("NOW")
if force:
args.append("FORCE")
if abort:
args.append("ABORT")
try:
self.execute_command(*args, **kwargs)
except ConnectionError:
# a ConnectionError here is expected
return
raise RedisError("SHUTDOWN seems to have failed.")
@overload
def slaveof(
self: SyncClientProtocol,
host: str | None = None,
port: int | None = None,
**kwargs,
) -> bool: ...
@overload
def slaveof(
self: AsyncClientProtocol,
host: str | None = None,
port: int | None = None,
**kwargs,
) -> Awaitable[bool]: ...
def slaveof(View on GitHub (pinned to 6a6b581b48)