redis/redis-py · error · RuntimeError

pubsub connection not set: did you forget to call subscribe(

Error message

pubsub connection not set: did you forget to call subscribe() or psubscribe()?

What it means

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.

Source

Thrown at redis/client.py:1377

            block=False when a timeout is provided, and block=True when timeout=None.

        Example:
            # Block indefinitely (timeout is ignored)
            response = pubsub.parse_response(block=True, timeout=0.1)

            # Non-blocking with 0.1 second timeout
            response = pubsub.parse_response(block=False, timeout=0.1)

            # Non-blocking, return immediately
            response = pubsub.parse_response(block=False, timeout=0)

            # Recommended: use get_message() instead
            msg = pubsub.get_message(timeout=0.1)  # automatically sets block=False
            msg = pubsub.get_message(timeout=None)  # automatically sets block=True
        """
        conn = self.connection
        if conn is None:
            raise RuntimeError(
                "pubsub connection not set: "
                "did you forget to call subscribe() or psubscribe()?"
            )

        self.check_health()

        def try_read():
            if not block:
                if not conn.can_read(timeout=timeout):
                    return None
                read_timeout = timeout
            else:
                conn.connect()
                # Block indefinitely waiting for a pubsub message. timeout=None
                # makes the socket layer call sock.settimeout(None) for this read
                # (and restore the original socket_timeout afterwards), so the
                # configured socket_timeout does not abort the read.
                read_timeout = None

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Call `ps.subscribe(channel)` (or psubscribe/ssubscribe) before the first `ps.get_message()` / `ps.parse_response()`.
  2. After any `ps.close()` or `ps.reset()`, re-subscribe before reading again.
  3. Prefer `ps.get_message(timeout=...)` over manual `parse_response` — it handles the subscribe lifecycle.
  4. If using an exception handler that resets the pubsub on error, ensure the recovery path re-invokes subscribe.

Example fix

# before
ps = client.pubsub()
msg = ps.get_message(timeout=1.0)  # raises RuntimeError

# after
ps = client.pubsub()
ps.subscribe('events')
msg = ps.get_message(timeout=1.0)
Defensive patterns

Strategy: validation

Validate before calling

ps = client.pubsub()
if not ps.subscribed:
    ps.subscribe('events')  # ensure a connection exists before reading

Type guard

def can_read_pubsub(ps) -> bool:
    return ps.connection is not None and ps.subscribed

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/ef8e08c578caca79.json. Report an issue: GitHub.