{"record":{"id":"2ef6422b17b8e47f","repo":"redis/redis-py","slug":"shard-channel-s-channel-has-no-handler-regist","errorCode":null,"errorMessage":"Shard Channel: '{s_channel}' has no handler registered","messagePattern":"Shard Channel: '(.+?)' has no handler registered","errorType":"exception","errorClass":"PubSubError","httpStatus":null,"severity":"error","filePath":"redis/client.py","lineNumber":1733,"sourceCode":"        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\nclass PubSubWorkerThread(threading.Thread):\n    def __init__(\n        self,","sourceCodeStart":1715,"sourceCodeEnd":1751,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/client.py#L1715-L1751","documentation":"Raised by PubSub.run_in_thread() when a shard channel (SSUBSCRIBE, Redis 7.0 sharded pubsub) has no handler. Same validation as 183/184 but iterating self.shard_channels. Required when sharded_pubsub=True is used with the worker thread.","triggerScenarios":"Calling ssubscribe on a PubSub (sharded) without a handler, then run_in_thread(sharded_pubsub=True). The loop at client.py:1731 raises for the None-mapped shard channel.","commonSituations":"Adopting Redis 7.0 sharded pubsub and reusing non-sharded polling code; forgetting the handler convention for shard channels.","solutions":["Register a handler per shard channel: pubsub.ssubscribe(**{'shardch': handler_fn}).","Pass sharded_pubsub=True to run_in_thread() and ensure all shard channels have callbacks.","Fall back to manual get_message() polling if handlers are not desired."],"exampleFix":"// before\npubsub.ssubscribe('shardch')\npubsub.run_in_thread(sharded_pubsub=True)  # PubSubError\n\n// after\ndef on_shard(msg): ...\npubsub.ssubscribe(**{'shardch': on_shard})\npubsub.run_in_thread(sharded_pubsub=True)","handlingStrategy":"validation","validationCode":"missing = [c for c, h in pubsub.shard_channels.items() if h is None]\nif missing:\n    raise ValueError(f'Shard channels missing handlers: {missing}')\npubsub.run_in_thread(sharded_pubsub=True)","typeGuard":"def all_shard_channels_have_handlers(pubsub) -> bool:\n    return all(h is not None for h in pubsub.shard_channels.values())","tryCatchPattern":"from redis.exceptions import PubSubError\ntry:\n    pubsub.run_in_thread(sharded_pubsub=True)\nexcept PubSubError:\n    for c in list(pubsub.shard_channels):\n        pubsub.shard_channels[c] = default_handler","preventionTips":["For sharded pubsub, always pass handlers with ssubscribe(**{name: handler}).","Remember to pass sharded_pubsub=True to run_in_thread().","Validate pubsub.shard_channels before starting the worker."],"tags":["pubsub","threading","sharded","api-misuse"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}