{"record":{"id":"3b697299e33f68d3","repo":"redis/redis-py","slug":"pattern-pattern-has-no-handler-registered-3b6972","errorCode":null,"errorMessage":"Pattern: '{pattern}' has no handler registered","messagePattern":"Pattern: '(.+?)' has no handler registered","errorType":"exception","errorClass":"PubSubError","httpStatus":null,"severity":"error","filePath":"redis/client.py","lineNumber":1730,"sourceCode":"            if ignore_subscribe_messages or self.ignore_subscribe_messages:\n                return None\n\n        return message\n\n    def run_in_thread(\n        self,\n        sleep_time: float = 0.0,\n        daemon: bool = False,\n        exception_handler: Optional[Callable] = None,\n        pubsub=None,\n        sharded_pubsub: bool = False,\n    ) -> \"PubSubWorkerThread\":\n        for channel, handler in self.channels.items():\n            if handler is None:\n                raise PubSubError(f\"Channel: '{channel}' has no handler registered\")\n        for pattern, handler in self.patterns.items():\n            if handler is None:\n                raise PubSubError(f\"Pattern: '{pattern}' has no handler registered\")\n        for s_channel, handler in self.shard_channels.items():\n            if handler is None:\n                raise PubSubError(\n                    f\"Shard Channel: '{s_channel}' has no handler registered\"\n                )\n\n        pubsub = self if pubsub is None else pubsub\n        thread = PubSubWorkerThread(\n            pubsub,\n            sleep_time,\n            daemon=daemon,\n            exception_handler=exception_handler,\n            sharded_pubsub=sharded_pubsub,\n        )\n        thread.start()\n        return thread\n\n","sourceCodeStart":1712,"sourceCodeEnd":1748,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/client.py#L1712-L1748","documentation":"Raised by PubSub.run_in_thread() when a subscribed pattern (PSUBSCRIBE) has no message handler. Symmetric to 183 but for the patterns dict — every pattern registered via psubscribe must carry a callback when run_in_thread is used.","triggerScenarios":"Calling pubsub.psubscribe('events.*') without a handler, then pubsub.run_in_thread(). The validation loop at client.py:1728 finds the pattern mapped to None and raises.","commonSituations":"Pattern subscriptions used with the threaded worker; forgetting that psubscribe requires the same handler convention as subscribe when threaded.","solutions":["Pass a handler with each pattern: pubsub.psubscribe(**{'events.*': handler_fn}).","Use manual get_message() polling in your own loop if you do not want per-pattern callbacks.","Confirm every key in pubsub.patterns has a callable value before run_in_thread()."],"exampleFix":"// before\npubsub.psubscribe('events.*')\npubsub.run_in_thread()  # PubSubError\n\n// after\ndef on_event(msg): ...\npubsub.psubscribe(**{'events.*': on_event})\npubsub.run_in_thread()","handlingStrategy":"validation","validationCode":"missing = [p for p, h in pubsub.patterns.items() if h is None]\nif missing:\n    raise ValueError(f'Patterns missing handlers: {missing}')\npubsub.run_in_thread()","typeGuard":"def all_patterns_have_handlers(pubsub) -> bool:\n    return all(h is not None for h in pubsub.patterns.values())","tryCatchPattern":"from redis.exceptions import PubSubError\ntry:\n    pubsub.run_in_thread()\nexcept PubSubError:\n    for p in list(pubsub.patterns):\n        pubsub.patterns[p] = default_handler","preventionTips":["Use psubscribe(**{pattern: handler}) when going threaded.","Keep the polling API and the threaded-dispatch API separate in your code.","Validate pubsub.patterns before run_in_thread()."],"tags":["pubsub","threading","api-misuse","patterns"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}