redis/redis-py · error · RedisError
MONITOR failed: {response}
Error message
MONITOR failed: {response} What it means
Raised by the async Monitor context manager (redis/asyncio/client.py:1092) inside __aenter__. After sending the MONITOR command the library reads the reply and checks it equals the OK status; any other reply means the server did not accept the monitor request. The original reply is interpolated into the message to aid diagnosis.
Source
Thrown at redis/asyncio/client.py:1092
monitor_re = re.compile(r"\[(\d+) (.*?)\] (.*)")
command_re = re.compile(r'"(.*?)(?<!\\)"')
def __init__(self, connection_pool: ConnectionPool):
self.connection_pool = connection_pool
self.connection: Optional[Connection] = None
async def connect(self):
if self.connection is None:
self.connection = await self.connection_pool.get_connection()
async def __aenter__(self):
await self.connect()
await self.connection.send_command("MONITOR")
# check that monitor returns 'OK', but don't return it to user
response = await self.connection.read_response()
if not bool_ok(response):
raise RedisError(f"MONITOR failed: {response}")
return self
async def __aexit__(self, *args):
await self.connection.disconnect()
await self.connection_pool.release(self.connection)
async def next_command(self) -> MonitorCommandInfo:
"""Parse the response from a monitor command"""
await self.connect()
response = await self.connection.read_response()
if isinstance(response, bytes):
response = self.connection.encoder.decode(response, force=True)
command_time, command_data = response.split(" ", 1)
m = self.monitor_re.match(command_data)
db_id, client_info, command = m.groups()
command = " ".join(self.command_re.findall(command))
# Redis escapes double quotes because each piece of the command
# string is surrounded by double quotes. We don't have thatView on GitHub (pinned to da03cdc7e8)
Solutions
- Use a Redis user/ACL that permits the MONITOR command (admin permission, or the default superuser).
- Confirm the target is a real Redis server (not a proxy/cluster node expecting a different command set) and that it has finished loading (INFO persistence loading:0).
- Wrap the context-manager entry in try/except RedisError and log response to capture the exact server refusal.
- If monitoring a cluster, attach the Monitor to a single node's connection rather than expecting cluster-wide streaming.
Example fix
// before
async with client.monitor() as m:
async for cmd in m.listen():
...
// after
default_user = redis.asyncio.Redis(url="redis://default:adminpw@host:6379")
try:
async with default_user.monitor() as m:
async for cmd in m.listen():
...
except redis.exceptions.RedisError as e:
log.error("monitor refused: %s", e) Defensive patterns
Strategy: try-catch
Try / catch
from redis.exceptions import RedisError
try:
async with client.monitor() as m:
async for cmd in m.listen():
...
except RedisError as e:
log.error("MONITOR refused by server: %s", e) Prevention
- Use an ACL user with admin/@slow permission for monitoring.
- Confirm the target is a direct Redis node (INFO server) and finished loading before monitoring.
- Avoid MONITOR in production hot paths; it degrades server throughput.
When it happens
Trigger: Using `async with client.monitor() as m:` against a server that refuses MONITOR. The server returns a non-OK reply such as an ACL/permission error (NOPERM), BUSYERR when the server is over capacity, or an error on a node that does not allow monitoring. The check is `if not bool_ok(response)`.
Common situations: Running MONITOR with a restricted ACL user that lacks the admin/@slow permission; pointing the client at a replica/proxy that strips MONITOR; hitting a max-clients or loading state where the server returns an error string instead of OK.
Related errors
- Maintenance notifications handlers on connection are only su
- pubsub connection not set: did you forget to call subscribe(
- Channel: '{channel}' has no handler registered
- Pattern: '{pattern}' has no handler registered
- Cannot issue nested calls to MULTI
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/5ee52de565c02c5c.json.
Report an issue: GitHub.