{"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/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/client.py#L1712-L1748","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Subscribe to patterns with a handler: `ps.psubscribe(**{'user.*': on_user_msg})`.","Confirm the dict key exactly matches the pattern you intend to handle.","Use a manual listen()/get_message loop if you do not want per-pattern callbacks."],"exampleFix":"# before\nps.psubscribe('user.*')\nps.run_in_thread()  # raises\n\n# after\ndef on_user(msg):\n    ...\nps.psubscribe(**{'user.*': on_user})\nps.run_in_thread()","handlingStrategy":"validation","validationCode":"if any(h is None for h in ps.patterns.values()):\n    raise RuntimeError('Register handlers for all patterns before run_in_thread')\nps.run_in_thread()","typeGuard":"def patterns_have_handlers(ps) -> bool:\n    return all(h is not None for h in ps.patterns.values())","tryCatchPattern":null,"preventionTips":["Pass pattern handlers via psubscribe(**{pattern: handler}).","Ensure pattern keys match exactly what you will receive."],"tags":["pubsub","threading","patterns","callbacks"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}