{"id":"ef8e08c578caca79","repo":"redis/redis-py","slug":"pubsub-connection-not-set-did-you-forget-to-call-ef8e08","errorCode":null,"errorMessage":"pubsub connection not set: did you forget to call subscribe() or psubscribe()?","messagePattern":"pubsub connection not set: did you forget to call subscribe\\(\\) or psubscribe\\(\\)\\?","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"redis/client.py","lineNumber":1377,"sourceCode":"            block=False when a timeout is provided, and block=True when timeout=None.\n\n        Example:\n            # Block indefinitely (timeout is ignored)\n            response = pubsub.parse_response(block=True, timeout=0.1)\n\n            # Non-blocking with 0.1 second timeout\n            response = pubsub.parse_response(block=False, timeout=0.1)\n\n            # Non-blocking, return immediately\n            response = pubsub.parse_response(block=False, timeout=0)\n\n            # Recommended: use get_message() instead\n            msg = pubsub.get_message(timeout=0.1)  # automatically sets block=False\n            msg = pubsub.get_message(timeout=None)  # automatically sets block=True\n        \"\"\"\n        conn = self.connection\n        if conn is None:\n            raise RuntimeError(\n                \"pubsub connection not set: \"\n                \"did you forget to call subscribe() or psubscribe()?\"\n            )\n\n        self.check_health()\n\n        def try_read():\n            if not block:\n                if not conn.can_read(timeout=timeout):\n                    return None\n                read_timeout = timeout\n            else:\n                conn.connect()\n                # Block indefinitely waiting for a pubsub message. timeout=None\n                # makes the socket layer call sock.settimeout(None) for this read\n                # (and restore the original socket_timeout afterwards), so the\n                # configured socket_timeout does not abort the read.\n                read_timeout = None","sourceCodeStart":1359,"sourceCodeEnd":1395,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/client.py#L1359-L1395","documentation":"Raised in `PubSub.parse_response` when `self.connection is None`. The pubsub connection is only created lazily inside `execute_command` the first time a subscribe-type command is issued. Calling `parse_response()` (or `get_message()`, which wraps it) before any subscribe means no connection exists, so the library raises a RuntimeError pointing at the missing subscribe call.","triggerScenarios":"Calling `pubsub.parse_response(...)` or `pubsub.get_message(...)` immediately after `client.pubsub()` without first calling `subscribe()`, `psubscribe()`, or `ssubscribe()`. Also happens if the PubSub was closed/reset (connection released) and then read from again without re-subscribing.","commonSituations":"Order-of-operations bugs in event loops; wrapping `get_message` in a retry loop that survives a close without re-subscribing; copy-paste from examples that omitted the subscribe line; calling parse_response manually instead of via get_message.","solutions":["Call `ps.subscribe(channel)` (or psubscribe/ssubscribe) before the first `ps.get_message()` / `ps.parse_response()`.","After any `ps.close()` or `ps.reset()`, re-subscribe before reading again.","Prefer `ps.get_message(timeout=...)` over manual `parse_response` — it handles the subscribe lifecycle.","If using an exception handler that resets the pubsub on error, ensure the recovery path re-invokes subscribe."],"exampleFix":"# before\nps = client.pubsub()\nmsg = ps.get_message(timeout=1.0)  # raises RuntimeError\n\n# after\nps = client.pubsub()\nps.subscribe('events')\nmsg = ps.get_message(timeout=1.0)","handlingStrategy":"validation","validationCode":"ps = client.pubsub()\nif not ps.subscribed:\n    ps.subscribe('events')  # ensure a connection exists before reading","typeGuard":"def can_read_pubsub(ps) -> bool:\n    return ps.connection is not None and ps.subscribed","tryCatchPattern":null,"preventionTips":["Always call subscribe/psubscribe before the first get_message.","Prefer get_message over manual parse_response.","Re-subscribe after close()/reset()."],"tags":["pubsub","lifecycle","usage"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}