redis/redis-py · error · RuntimeError

pubsub connection not set: did you forget to call…

Error message

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

What it means

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.

Solutions

  1. Call subscribe()/psubscribe()/ssubscribe() with at least one channel/pattern before parse_response() or get_message().
  2. Verify pubsub.connection is not None before reading, or wrap get_message() in a guard.
  3. Ensure you are not reusing a PubSub object after calling close()/reset().

Example fix

// before
pubsub = r.pubsub()
msg = pubsub.get_message(timeout=1.0)  # RuntimeError

// after
pubsub = r.pubsub()
pubsub.subscribe('channel')
msg = pubsub.get_message(timeout=1.0)
Defensive patterns

Strategy: validation

Validate before calling

if pubsub.connection is None:
    pubsub.subscribe('channel')  # bind a connection first
response = pubsub.parse_response(block=False, timeout=0.1)

Type guard

def pubsub_is_subscribed(pubsub) -> bool:
    return pubsub.connection is not None

Try / catch

if pubsub.connection is None:
    raise RuntimeError('Call subscribe() before polling')
msg = pubsub.get_message(timeout=0.1)

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/ef8e08c578caca79. Report an issue: GitHub.

Appendix: 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 6a6b581b48)