{"id":"5ee52de565c02c5c","repo":"redis/redis-py","slug":"monitor-failed-response","errorCode":null,"errorMessage":"MONITOR failed: {response}","messagePattern":"MONITOR failed: (.+?)","errorType":"exception","errorClass":"RedisError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/client.py","lineNumber":1092,"sourceCode":"\n    monitor_re = re.compile(r\"\\[(\\d+) (.*?)\\] (.*)\")\n    command_re = re.compile(r'\"(.*?)(?<!\\\\)\"')\n\n    def __init__(self, connection_pool: ConnectionPool):\n        self.connection_pool = connection_pool\n        self.connection: Optional[Connection] = None\n\n    async def connect(self):\n        if self.connection is None:\n            self.connection = await self.connection_pool.get_connection()\n\n    async def __aenter__(self):\n        await self.connect()\n        await self.connection.send_command(\"MONITOR\")\n        # check that monitor returns 'OK', but don't return it to user\n        response = await self.connection.read_response()\n        if not bool_ok(response):\n            raise RedisError(f\"MONITOR failed: {response}\")\n        return self\n\n    async def __aexit__(self, *args):\n        await self.connection.disconnect()\n        await self.connection_pool.release(self.connection)\n\n    async def next_command(self) -> MonitorCommandInfo:\n        \"\"\"Parse the response from a monitor command\"\"\"\n        await self.connect()\n        response = await self.connection.read_response()\n        if isinstance(response, bytes):\n            response = self.connection.encoder.decode(response, force=True)\n        command_time, command_data = response.split(\" \", 1)\n        m = self.monitor_re.match(command_data)\n        db_id, client_info, command = m.groups()\n        command = \" \".join(self.command_re.findall(command))\n        # Redis escapes double quotes because each piece of the command\n        # string is surrounded by double quotes. We don't have that","sourceCodeStart":1074,"sourceCodeEnd":1110,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/client.py#L1074-L1110","documentation":"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.","triggerScenarios":"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)`.","commonSituations":"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.","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."],"exampleFix":"// before\nasync with client.monitor() as m:\n    async for cmd in m.listen():\n        ...\n// after\ndefault_user = redis.asyncio.Redis(url=\"redis://default:adminpw@host:6379\")\ntry:\n    async with default_user.monitor() as m:\n        async for cmd in m.listen():\n            ...\nexcept redis.exceptions.RedisError as e:\n    log.error(\"monitor refused: %s\", e)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from redis.exceptions import RedisError\ntry:\n    async with client.monitor() as m:\n        async for cmd in m.listen():\n            ...\nexcept RedisError as e:\n    log.error(\"MONITOR refused by server: %s\", e)","preventionTips":["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."],"tags":["redis","asyncio","monitor","permissions","server-error"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}