redis/redis-py · error · PubSubError
Pattern: '{pattern}' has no handler registered
Error message
Pattern: '{pattern}' has no handler registered What it means
Raised by PubSub.run() (redis/asyncio/client.py:1746) when iterating self.patterns and finding a pattern whose handler is None. Symmetric to the channel case: the callback worker requires every psubscribe() pattern to carry a callable. It raises PubSubError naming the offending pattern.
Source
Thrown at redis/asyncio/client.py:1746
"""Process pub/sub messages using registered callbacks.
This is the equivalent of :py:meth:`redis.PubSub.run_in_thread` in
redis-py, but it is a coroutine. To launch it as a separate task, use
``asyncio.create_task``:
>>> task = asyncio.create_task(pubsub.run())
To shut it down, use asyncio cancellation:
>>> task.cancel()
>>> await task
"""
for channel, handler in self.channels.items():
if handler is None:
raise PubSubError(f"Channel: '{channel}' has no handler registered")
for pattern, handler in self.patterns.items():
if handler is None:
raise PubSubError(f"Pattern: '{pattern}' has no handler registered")
await self.connect()
while True:
try:
if pubsub is None:
await self.get_message(
ignore_subscribe_messages=True, timeout=poll_timeout
)
else:
await pubsub.get_message(
ignore_subscribe_messages=True, timeout=poll_timeout
)
except asyncio.CancelledError:
raise
except BaseException as e:
if exception_handler is None:
raise
res = exception_handler(e, self)View on GitHub (pinned to da03cdc7e8)
Solutions
- Register a callback per pattern: `await pubsub.psubscribe(**{'chan:*': handler})`.
- Use get_message() instead of run() for manual dispatch.
- Before run(), assert every entry in pubsub.patterns has a non-None handler.
Example fix
// before
await pubsub.psubscribe('chan:*')
task = asyncio.create_task(pubsub.run())
// after
async def handler(msg):
...
await pubsub.psubscribe(**{'chan:*': handler})
task = asyncio.create_task(pubsub.run()) Defensive patterns
Strategy: validation
Validate before calling
async def handler(msg): ...
pubsub = r.pubsub()
await pubsub.psubscribe(**{'chan:*': handler})
assert all(h is not None for h in pubsub.patterns.values())
task = asyncio.create_task(pubsub.run()) Prevention
- Pass callbacks for every psubscribe() pattern when using run().
- Assert no None handlers exist in pubsub.patterns before launching the worker.
- Use get_message() for manual pattern dispatch.
When it happens
Trigger: Calling `await pubsub.psubscribe('chan:*')` without a callback then starting `pubsub.run()`. Pattern handlers must be passed as `pubsub.psubscribe(**{'chan:*': handler})`.
Common situations: Subscribing to glob patterns for manual dispatch but then switching to the run() worker without converting subscriptions to the callback form.
Related errors
- Channel: '{channel}' has no handler registered
- pubsub connection not set: did you forget to call subscribe(
- Cannot issue nested calls to MULTI
- Commands without an initial WATCH have already been issued
- Cannot issue a WATCH after a MULTI
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/6bc4e801d4ca6b5d.json.
Report an issue: GitHub.