{"record":{"id":"d8741669070a3ace","repo":"redis/redis-py","slug":"rediscluster-requires-at-least-one-node-to-discove","errorCode":null,"errorMessage":"RedisCluster requires at least one node to discover the cluster.\nPlease provide one of the following or use RedisCluster.from_url:\n   - host and port: RedisCluster(host=\"localhost\", port=6379)\n   - startup_nodes: RedisCluster(startup_nodes=[ClusterNode(\"localhost\", 6379), ClusterNode(\"localhost\", 6380)])","messagePattern":"RedisCluster requires at least one node to discover the cluster\\.\nPlease provide one of the following or use RedisCluster\\.from_url:\n   - host and port: RedisCluster\\(host=\"localhost\", port=6379\\)\n   - startup_nodes: RedisCluster\\(startup_nodes=\\[ClusterNode\\(\"localhost\", 6379\\), ClusterNode\\(\"localhost\", 6380\\)\\]\\)","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/asyncio/cluster.py","lineNumber":472,"sourceCode":"        protocol: int | None = None,\n        legacy_responses: bool = True,\n        address_remap: Callable[[Tuple[str, int]], Tuple[str, int]] | None = None,\n        event_dispatcher: EventDispatcher | None = None,\n        policy_resolver: AsyncPolicyResolver = AsyncStaticPolicyResolver(),\n        maint_notifications_config: MaintNotificationsConfig | None = None,\n    ) -> None:\n        if db:\n            raise RedisClusterException(\n                \"Argument 'db' must be 0 or None in cluster mode\"\n            )\n\n        if path:\n            raise RedisClusterException(\n                \"Unix domain socket is not supported in cluster mode\"\n            )\n\n        if (not host or not port) and not startup_nodes:\n            raise RedisClusterException(\n                \"RedisCluster requires at least one node to discover the cluster.\\n\"\n                \"Please provide one of the following or use RedisCluster.from_url:\\n\"\n                '   - host and port: RedisCluster(host=\"localhost\", port=6379)\\n'\n                \"   - startup_nodes: RedisCluster(startup_nodes=[\"\n                'ClusterNode(\"localhost\", 6379), ClusterNode(\"localhost\", 6380)])'\n            )\n\n        computed_driver_info = resolve_driver_info(driver_info, lib_name, lib_version)\n\n        kwargs: Dict[str, Any] = {\n            \"max_connections\": max_connections,\n            \"connection_class\": Connection,\n            # Client related kwargs\n            \"credential_provider\": credential_provider,\n            \"username\": username,\n            \"password\": password,\n            \"client_name\": client_name,\n            \"driver_info\": computed_driver_info,","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/cluster.py#L454-L490","documentation":"Raised in RedisCluster.__init__ when neither (host and port) nor startup_nodes is provided. The cluster client needs at least one seed node to bootstrap slot/topology discovery via CLUSTER NODES / CLUSTER SHARDS. With no seed it cannot discover anything, so construction fails fast with a hint pointing at from_url as an alternative.","triggerScenarios":"RedisCluster() with no args; RedisCluster(host='localhost') missing port; passing only host or only port; passing an empty startup_nodes list.","commonSituations":"Building a cluster client from environment variables where REDIS_HOST/REDIS_PORT are unset in one environment; misconfiguring service discovery; copy-paste dropping the port argument.","solutions":["Provide host and port: RedisCluster(host='localhost', port=7000).","Or provide startup_nodes=[ClusterNode('host', port), ...].","Or use RedisCluster.from_url('redis://host:port') which parses the URL into a seed node."],"exampleFix":"// before\nclient = RedisCluster()\n// after\nclient = RedisCluster(host='localhost', port=7000)\n# or\nclient = RedisCluster.from_url('redis://localhost:7000')","handlingStrategy":"validation","validationCode":"has_seed = (host and port) or bool(startup_nodes)\nassert has_seed, 'RedisCluster needs host+port or startup_nodes'\nclient = RedisCluster(host=host, port=port, startup_nodes=startup_nodes)","typeGuard":"def has_cluster_seed(host, port, startup_nodes) -> bool:\n    return bool((host and port) or startup_nodes)","tryCatchPattern":"from redis.exceptions import RedisClusterException\ntry:\n    client = RedisCluster(host=host, port=port)\nexcept RedisClusterException as e:\n    if 'at least one node' in str(e):\n        client = RedisCluster.from_url(os.environ['REDIS_URL'])\n    else:\n        raise","preventionTips":["Always pass host+port or a non-empty startup_nodes list.","Fall back to from_url when a URL is available."],"tags":["cluster","configuration","init","discovery"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}