From 209163643aab3d403f0218b97cd40c9d2ff527d5 Mon Sep 17 00:00:00 2001 From: "Edmund L. Wong" Date: Mon, 16 Dec 2024 23:39:39 -0800 Subject: [PATCH] Fix AttributeError when client.get_default_node() returns None --- redis/asyncio/cluster.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/redis/asyncio/cluster.py b/redis/asyncio/cluster.py index 4e82e5448f..c29c08e50a 100644 --- a/redis/asyncio/cluster.py +++ b/redis/asyncio/cluster.py @@ -1568,18 +1568,22 @@ async def _execute( result.args = (msg,) + result.args[1:] raise result - default_node = nodes.get(client.get_default_node().name) - if default_node is not None: - # This pipeline execution used the default node, check if we need - # to replace it. - # Note: when the error is raised we'll reset the default node in the - # caller function. - for cmd in default_node[1]: - # Check if it has a command that failed with a relevant - # exception - if type(cmd.result) in self.__class__.ERRORS_ALLOW_RETRY: - client.replace_default_node() - break + default_cluster_node = client.get_default_node() + if default_cluster_node is not None: + # Not sure why default_cluster_node is sometimes None; maybe if the object is being + # closed during an execution? Either way, this avoids a potential AttributeError + default_node = nodes.get(default_cluster_node.name) + if default_node is not None: + # This pipeline execution used the default node, check if we need + # to replace it. + # Note: when the error is raised we'll reset the default node in the + # caller function. + for cmd in default_node[1]: + # Check if it has a command that failed with a relevant + # exception + if type(cmd.result) in self.__class__.ERRORS_ALLOW_RETRY: + client.replace_default_node() + break return [cmd.result for cmd in stack]