{"record":{"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/6a6b581b48225afa0b76912d1028c6035baee932/redis/client.py#L1359-L1395","documentation":"Raised by PubSub.parse_response() when self.connection is None — i.e. the PubSub object has never had a connection bound to it. A connection is only created lazily by subscribe()/psubscribe()/ssubscribe(), so calling parse_response() before any subscribe call has no socket to read from.","triggerScenarios":"Calling pubsub.parse_response() (directly or via get_message()) on a PubSub object before calling subscribe(), psubscribe(), or ssubscribe(). Also reachable if the connection was explicitly closed/reset before parse_response.","commonSituations":"Ordering bug: get_message() invoked before subscribe(); copy-pasting example code that omits the subscribe step; calling close() on the pubsub then continuing to poll.","solutions":["Call subscribe()/psubscribe()/ssubscribe() with at least one channel/pattern before parse_response() or get_message().","Verify pubsub.connection is not None before reading, or wrap get_message() in a guard.","Ensure you are not reusing a PubSub object after calling close()/reset()."],"exampleFix":"// before\npubsub = r.pubsub()\nmsg = pubsub.get_message(timeout=1.0)  # RuntimeError\n\n// after\npubsub = r.pubsub()\npubsub.subscribe('channel')\nmsg = pubsub.get_message(timeout=1.0)","handlingStrategy":"validation","validationCode":"if pubsub.connection is None:\n    pubsub.subscribe('channel')  # bind a connection first\nresponse = pubsub.parse_response(block=False, timeout=0.1)","typeGuard":"def pubsub_is_subscribed(pubsub) -> bool:\n    return pubsub.connection is not None","tryCatchPattern":"if pubsub.connection is None:\n    raise RuntimeError('Call subscribe() before polling')\nmsg = pubsub.get_message(timeout=0.1)","preventionTips":["Always subscribe before get_message()/parse_response().","Do not reuse a PubSub after close(); obtain a new one via client.pubsub().","Centralize pubsub lifecycle in a helper that enforces subscribe-first ordering."],"tags":["pubsub","api-misuse","connection"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}