redis/redis-py · error · RedisError

Maintenance notifications are only supported with RESP…

Error message

Maintenance notifications are only supported with RESP version 3

What it means

Raised by RedisCluster.__init__ when maintenance notifications (maint_notifications_config with enabled=True) are requested but the protocol is not RESP3. Maintenance notifications are delivered as RESP3 push messages, so enabling them requires negotiating RESP3. The guard is at cluster.py:894.

Solutions

  1. Set protocol=3 when enabling maintenance notifications: RedisCluster(host=..., protocol=3, maint_notifications_config=...).
  2. Ensure the endpoint/proxy actually supports RESP3 (some older proxies downgrade).
  3. Leave maint_notifications_config disabled (or None) if you cannot use RESP3.

Example fix

// before
cfg = MaintNotificationsConfig(enabled=True)
client = RedisCluster(host='localhost', port=7000, maint_notifications_config=cfg)  # RedisError

// after
cfg = MaintNotificationsConfig(enabled=True)
client = RedisCluster(host='localhost', port=7000, protocol=3, maint_notifications_config=cfg)
Defensive patterns

Strategy: validation

Validate before calling

from redis._parsers.helpers import check_protocol_version
protocol = kwargs.get('protocol')
if maint_notifications_config and maint_notifications_config.enabled and not check_protocol_version(protocol, 3):
    kwargs['protocol'] = 3
client = RedisCluster(host='localhost', port=7000, protocol=kwargs.get('protocol', 3), maint_notifications_config=maint_notifications_config)

Type guard

def maint_notifications_resp3_compatible(kwargs, cfg) -> bool:
    from redis._parsers.helpers import check_protocol_version
    return not (cfg and cfg.enabled) or check_protocol_version(kwargs.get('protocol'), 3)

Try / catch

from redis.exceptions import RedisError
try:
    client = RedisCluster(host='localhost', port=7000, maint_notifications_config=cfg)
except RedisError as e:
    if 'RESP version 3' in str(e):
        client = RedisCluster(host='localhost', port=7000, protocol=3, maint_notifications_config=cfg)
    else:
        raise

Prevention

When it happens

Trigger: RedisCluster(host=..., maint_notifications_config=MaintNotificationsConfig(enabled=True)) without protocol=3.

Common situations: Turning on maintenance-notification handling for managed Redis (Redis Cloud) without switching the wire protocol; inheriting a config object whose enabled flag defaults True; deploying to an environment where RESP3 is disabled by a proxy.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/7a4d222a1bf1d549. Report an issue: GitHub.

Appendix: source

Thrown at redis/cluster.py:894

                ),
                retries=cluster_error_retry_attempts,
            )

        self.encoder = Encoder(
            kwargs.get("encoding", "utf-8"),
            kwargs.get("encoding_errors", "strict"),
            kwargs.get("decode_responses", False),
        )
        protocol = kwargs.get("protocol", None)
        if (cache_config or cache) and not check_protocol_version(protocol, 3):
            raise RedisError("Client caching is only supported with RESP version 3")

        if (
            maint_notifications_config
            and maint_notifications_config.enabled
            and not check_protocol_version(protocol, 3)
        ):
            raise RedisError(
                "Maintenance notifications are only supported with RESP version 3"
            )
        if check_protocol_version(protocol, 3) and maint_notifications_config is None:
            maint_notifications_config = MaintNotificationsConfig()

        # Build the client-level HIMPORT registry once (always empty at construction)
        # and share the same object with every node pool, so the fieldset registry is
        # shared cluster-wide and runtime himport_prepare mutates one object. It is
        # handed to the NodesManager and injected onto each node's pool in
        # create_redis_node; it is deliberately NOT forwarded through connection_kwargs,
        # so nodes reuse the one shared object rather than each rebuilding their own.
        self._himport_registry = HImportRegistry()

        self.command_flags = self.__class__.COMMAND_FLAGS.copy()
        self.node_flags = self.__class__.NODE_FLAGS.copy()
        self.read_from_replicas = read_from_replicas
        self.load_balancing_strategy = load_balancing_strategy
        self.reinitialize_counter = 0

View on GitHub (pinned to 6a6b581b48)