def is_failover_possible(self, cluster: Cluster, leader: Optional[str], candidate: Optional[str],
                             action: str) -> Optional[str]:
        """Checks whether there are nodes that could take over after demoting the primary.

        :param cluster: the Patroni cluster.
        :param leader: name of the current Patroni leader.
        :param candidate: name of the Patroni node to be promoted.
        :param action: the action to be performed (``switchover`` or ``failover``).

        :returns: a string with the error message or ``None`` if good nodes are found.
        """
        config = global_config.from_cluster(cluster)
        if leader and (not cluster.leader or cluster.leader.name != leader):
            return 'leader name does not match'
        if candidate:
            if action == 'switchover' and config.is_synchronous_mode\
                    and not config.is_quorum_commit_mode and not cluster.sync.matches(candidate):
                return 'candidate name does not match with sync_standby'
            members = [m for m in cluster.members if m.name == candidate]
            if not members:
                return 'candidate does not exists'
        elif config.is_synchronous_mode and not config.is_quorum_commit_mode:
            members = [m for m in cluster.members if cluster.sync.matches(m.name)]
            if not members:
                return action + ' is not possible: can not find sync_standby'
        else:
            members = [m for m in cluster.members if not cluster.leader or m.name != cluster.leader.name and m.api_url]
            if not members:
                return action + ' is not possible: cluster does not have members except leader'
        for st in self.server.patroni.ha.fetch_nodes_statuses(members):
            if st.failover_limitation() is None:
                return None
        return action + ' is not possible: no good candidates have been found'
Checks whether there are nodes that could take over after demoting the primary.

        :param cluster: the Patroni cluster.
        :param leader: name of the current Patroni leader.
        :param candidate: name of the Patroni node to be promoted.
        :param action: the action to be performed (``switchover`` or ``failover``).

        :returns: a string with the error message or ``None`` if good nodes are found.
        
patroni/api.py