{"id":"16d7683242527051","repo":"redis/redis-py","slug":"either-maint-notifications-pool-handler-or-oss-clu-16d768","errorCode":null,"errorMessage":"Either maint_notifications_pool_handler or oss_cluster_maint_notifications_handler must be set","messagePattern":"Either maint_notifications_pool_handler or oss_cluster_maint_notifications_handler must be set","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"redis/connection.py","lineNumber":2684,"sourceCode":"        with self._get_pool_lock():\n            for conn in self._get_free_connections():\n                if oss_cluster_maint_notifications_handler:\n                    # set cluster handler for conn\n                    conn.set_maint_notifications_cluster_handler_for_connection(\n                        oss_cluster_maint_notifications_handler\n                    )\n                    conn.maint_notifications_config = (\n                        oss_cluster_maint_notifications_handler.config\n                    )\n                elif maint_notifications_pool_handler:\n                    conn.set_maint_notifications_pool_handler_for_connection(\n                        maint_notifications_pool_handler\n                    )\n                    conn.maint_notifications_config = (\n                        maint_notifications_pool_handler.config\n                    )\n                else:\n                    raise ValueError(\n                        \"Either maint_notifications_pool_handler or oss_cluster_maint_notifications_handler must be set\"\n                    )\n                conn.disconnect()\n            for conn in self._get_in_use_connections():\n                if oss_cluster_maint_notifications_handler:\n                    # Use set_maint_notifications_cluster_handler_for_connection\n                    # (not _configure_maintenance_notifications) so the parser is\n                    # obtained from the connection itself. _configure_* requires a\n                    # parser argument and would raise here; it would also reset the\n                    # connection's orig_* settings, which is wrong for an in-use\n                    # (active) connection. This mirrors the idle-connection branch\n                    # above and the pool-handler branches.\n                    conn.set_maint_notifications_cluster_handler_for_connection(\n                        oss_cluster_maint_notifications_handler\n                    )\n                    conn.maint_notifications_config = (\n                        oss_cluster_maint_notifications_handler.config\n                    )","sourceCodeStart":2666,"sourceCodeEnd":2702,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/connection.py#L2666-L2702","documentation":"Raised as a ValueError by _update_maint_notifications_configs_for_connections (connection.py:2683-2686) in the idle/free-connections branch when neither maint_notifications_pool_handler nor oss_cluster_maint_notifications_handler is passed. This is an internal reconfiguration helper invoked after handler setup; both being None means there is no handler to push to connections, which is a programming error in the calling code rather than user config.","triggerScenarios":"Internal/library code (or a subclass override) calling _update_maint_notifications_configs_for_connections with both handler arguments omitted/None. Not reachable through normal public API usage under correct internal flow, because update_maint_notifications_config always supplies one before calling it.","commonSituations":"Subclassing the connection pool and overriding/wrapping maintenance-notification logic but forgetting to forward a handler; race during reconfiguration where handlers are cleared before the update runs; bugs in custom pool extensions.","solutions":["If you subclass or call _update_maint_notifications_configs_for_connections directly, always pass exactly one of the two handlers (pool handler or OSS cluster handler).","Use the public update_maint_notifications_config() entry point instead of the internal helper — it validates and supplies the handler for you.","Ensure you are on a current redis-py version; if hitting this through normal API calls, report it as a bug after confirming no subclass is involved."],"exampleFix":"# before (internal helper called without a handler)\npool._update_maint_notifications_configs_for_connections(\n    maint_notifications_pool_handler=None,\n    oss_cluster_maint_notifications_handler=None)\n\n# after (use the public API, which supplies a handler)\npool.update_maint_notifications_config(\n    MaintNotificationsConfig(enabled=True))","handlingStrategy":"validation","validationCode":"def safe_update_configs(pool, pool_handler=None, oss_handler=None):\n    if pool_handler is None and oss_handler is None:\n        raise ValueError(\"Exactly one handler (pool or oss) must be provided\")\n    pool._update_maint_notifications_configs_for_connections(\n        maint_notifications_pool_handler=pool_handler,\n        oss_cluster_maint_notifications_handler=oss_handler)","typeGuard":"def exactly_one_handler(pool_handler, oss_handler) -> bool:\n    return (pool_handler is not None) ^ (oss_handler is not None)","tryCatchPattern":"try:\n    pool._update_maint_notifications_configs_for_connections(\n        maint_notifications_pool_handler=h1, oss_cluster_maint_notifications_handler=h2)\nexcept ValueError as e:\n    if \"must be set\" in str(e):\n        # fall back to the public API which supplies a handler\n        pool.update_maint_notifications_config(MaintNotificationsConfig(enabled=True))\n    else:\n        raise","preventionTips":["Use the public update_maint_notifications_config() API instead of the internal helper.","If subclassing the pool, always forward exactly one handler to the internal helper.","Add assertions in custom pool code that one handler is non-None before reconfiguring connections."],"tags":["maintenance-notifications","internal","validation","lifecycle"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}