{"id":"932bde4ea5e8f477","repo":"redis/redis-py","slug":"pattern-pattern-has-no-handler-registered-932bde","errorCode":null,"errorMessage":"Pattern '{pattern}' has no handler registered","messagePattern":"Pattern '(.+?)' has no handler registered","errorType":"exception","errorClass":"RedisError","httpStatus":null,"severity":"warning","filePath":"redis/keyspace_notifications.py","lineNumber":1728,"sourceCode":"        \"\"\"\n        while self.subscribed:\n            notification = self.get_message(timeout=1.0)\n            if notification is not None:\n                yield notification\n\n    @property\n    def subscribed(self) -> bool:\n        \"\"\"Check if there are any active subscriptions and not closed.\"\"\"\n        return not self._closed and self._pubsub.subscribed\n\n    def _validate_all_handlers(self) -> None:\n        \"\"\"Raise if any subscription in the underlying PubSub lacks a handler.\"\"\"\n        for channel, handler in self._pubsub.channels.items():\n            if handler is None:\n                raise RedisError(f\"Channel '{channel}' has no handler registered\")\n        for pattern, handler in self._pubsub.patterns.items():\n            if handler is None:\n                raise RedisError(f\"Pattern '{pattern}' has no handler registered\")\n\n    def close(self):\n        \"\"\"Close the pubsub connection and clean up resources.\"\"\"\n        self._closed = True\n        try:\n            self._pubsub.close()\n        except Exception:\n            pass\n\n\n# =============================================================================\n# Cluster-Aware Keyspace Notification Manager\n# =============================================================================\n\n\nclass ClusterKeyspaceNotifications(AbstractKeyspaceNotifications):\n    \"\"\"\n    Manages keyspace notification subscriptions across all nodes in a Redis Cluster.","sourceCodeStart":1710,"sourceCodeEnd":1746,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/keyspace_notifications.py#L1710-L1746","documentation":"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.","triggerScenarios":"Calling run_in_thread() (standalone Redis) after subscribing to a pattern channel (a string/KeyspaceChannel containing *, ?, [) without a handler= callback.","commonSituations":"Subscribing with a wildcard pattern for polling, then trying to use the handler-based worker thread; forgetting the handler on a pattern subscription.","solutions":["Pass handler= when subscribing to any pattern channel before run_in_thread().","Use get_message()/listen() for handler-less polling instead of the worker thread.","Unsubscribe handler-less patterns before starting the worker."],"exampleFix":"// before\nnotifications.subscribe('user:*')  # pattern, no handler\nthread = notifications.run_in_thread(poll_timeout=0.1)  # raises\n\n// after\ndef on_evt(n):\n    print(n.key, n.event_type)\nnotifications.subscribe('user:*', handler=on_evt)\nthread = notifications.run_in_thread(poll_timeout=0.1)","handlingStrategy":"validation","validationCode":"for pat, h in notifications._pubsub.patterns.items():\n    if h is None:\n        raise RuntimeError(f'pattern {pat!r} lacks a handler')\nnotifications.run_in_thread(poll_timeout=0.1)","typeGuard":"def all_patterns_have_handler(ksn) -> bool:\n    return all(h is not None for h in ksn._pubsub.patterns.values())","tryCatchPattern":null,"preventionTips":["Pass handler= for every pattern subscription before run_in_thread().","Use get_message()/listen() for handler-less polling.","Unsubscribe handler-less patterns before starting the worker.","Keep the dispatch model consistent across channel and pattern subscriptions."],"tags":["keyspace-notifications","pubsub","validation","rediserror","pattern"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}