redis/redis-py · error · PubSubError

Pattern: '{pattern}' has no handler registered

Error message

Pattern: '{pattern}' has no handler registered

What it means

Raised in `PubSub.run_in_thread` when a pattern subscription (`psubscribe`) has a None handler. Same validation as for channels but iterating `self.patterns`. The worker thread dispatches pmessage frames using the pattern-keyed handler map, so a missing handler is treated as a fatal PubSubError before the thread starts.

Source

Thrown at redis/client.py:1730

            if ignore_subscribe_messages or self.ignore_subscribe_messages:
                return None

        return message

    def run_in_thread(
        self,
        sleep_time: float = 0.0,
        daemon: bool = False,
        exception_handler: Optional[Callable] = None,
        pubsub=None,
        sharded_pubsub: bool = False,
    ) -> "PubSubWorkerThread":
        for channel, handler in self.channels.items():
            if handler is None:
                raise PubSubError(f"Channel: '{channel}' has no handler registered")
        for pattern, handler in self.patterns.items():
            if handler is None:
                raise PubSubError(f"Pattern: '{pattern}' has no handler registered")
        for s_channel, handler in self.shard_channels.items():
            if handler is None:
                raise PubSubError(
                    f"Shard Channel: '{s_channel}' has no handler registered"
                )

        pubsub = self if pubsub is None else pubsub
        thread = PubSubWorkerThread(
            pubsub,
            sleep_time,
            daemon=daemon,
            exception_handler=exception_handler,
            sharded_pubsub=sharded_pubsub,
        )
        thread.start()
        return thread

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Subscribe to patterns with a handler: `ps.psubscribe(**{'user.*': on_user_msg})`.
  2. Confirm the dict key exactly matches the pattern you intend to handle.
  3. Use a manual listen()/get_message loop if you do not want per-pattern callbacks.

Example fix

# before
ps.psubscribe('user.*')
ps.run_in_thread()  # raises

# after
def on_user(msg):
    ...
ps.psubscribe(**{'user.*': on_user})
ps.run_in_thread()
Defensive patterns

Strategy: validation

Validate before calling

if any(h is None for h in ps.patterns.values()):
    raise RuntimeError('Register handlers for all patterns before run_in_thread')
ps.run_in_thread()

Type guard

def patterns_have_handlers(ps) -> bool:
    return all(h is not None for h in ps.patterns.values())

Prevention

When it happens

Trigger: Calling `ps.psubscribe('user.*')` without a callback and then `ps.run_in_thread()`. Pattern subscriptions must be registered with a callable (`ps.psubscribe(**{'user.*': handler})`) for the threaded dispatcher to route pmessage frames.

Common situations: Switching a pattern-based pubsub consumer from a manual `listen()` loop to `run_in_thread` without supplying pattern callbacks; typo in the dict key passed to psubscribe causing the handler to land under a different pattern.

Related errors


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