redis/redis-py · warning · RedisError

Pattern '{pattern}' has no handler registered

Error message

Pattern '{pattern}' has no handler registered

What it means

Raised as redis.exceptions.RedisError by StandaloneKeyspaceNotifications._validate_all_handlers (redis/keyspace_notifications.py:1728). The pattern counterpart of the channel check: every subscribed pattern (glob-style, with wildcards) in the PubSub must have a handler before run_in_thread() starts, otherwise an arriving pattern notification would have nowhere to dispatch.

Source

Thrown at redis/keyspace_notifications.py:1728

        """
        while self.subscribed:
            notification = self.get_message(timeout=1.0)
            if notification is not None:
                yield notification

    @property
    def subscribed(self) -> bool:
        """Check if there are any active subscriptions and not closed."""
        return not self._closed and self._pubsub.subscribed

    def _validate_all_handlers(self) -> None:
        """Raise if any subscription in the underlying PubSub lacks a handler."""
        for channel, handler in self._pubsub.channels.items():
            if handler is None:
                raise RedisError(f"Channel '{channel}' has no handler registered")
        for pattern, handler in self._pubsub.patterns.items():
            if handler is None:
                raise RedisError(f"Pattern '{pattern}' has no handler registered")

    def close(self):
        """Close the pubsub connection and clean up resources."""
        self._closed = True
        try:
            self._pubsub.close()
        except Exception:
            pass


# =============================================================================
# Cluster-Aware Keyspace Notification Manager
# =============================================================================


class ClusterKeyspaceNotifications(AbstractKeyspaceNotifications):
    """
    Manages keyspace notification subscriptions across all nodes in a Redis Cluster.

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass handler= when subscribing to any pattern channel before run_in_thread().
  2. Use get_message()/listen() for handler-less polling instead of the worker thread.
  3. Unsubscribe handler-less patterns before starting the worker.

Example fix

// before
notifications.subscribe('user:*')  # pattern, no handler
thread = notifications.run_in_thread(poll_timeout=0.1)  # raises

// after
def on_evt(n):
    print(n.key, n.event_type)
notifications.subscribe('user:*', handler=on_evt)
thread = notifications.run_in_thread(poll_timeout=0.1)
Defensive patterns

Strategy: validation

Validate before calling

for pat, h in notifications._pubsub.patterns.items():
    if h is None:
        raise RuntimeError(f'pattern {pat!r} lacks a handler')
notifications.run_in_thread(poll_timeout=0.1)

Type guard

def all_patterns_have_handler(ksn) -> bool:
    return all(h is not None for h in ksn._pubsub.patterns.values())

Prevention

When it happens

Trigger: Calling run_in_thread() (standalone Redis) after subscribing to a pattern channel (a string/KeyspaceChannel containing *, ?, [) without a handler= callback.

Common situations: Subscribing with a wildcard pattern for polling, then trying to use the handler-based worker thread; forgetting the handler on a pattern subscription.

Related errors


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