# Buggy code
def _fetch(self):
    """
    Fetch the repo. If the local copy was updated, return True. If the
    local copy was already up-to-date, return False.
    """
    origin = self.repo.remotes[0]
    refs_pre = self.repo.listall_references()
    fetch_kwargs = {}
    if self.credentials is not None:
        if self.use_callback:
            fetch_kwargs["callbacks"] = pygit2.RemoteCallbacks(
                credentials=self.credentials
            )
        else:
            origin.credentials = self.credentials
    try:
        fetch_results = origin.fetch(**fetch_kwargs)
    except GitError as exc:
        # Using exc.__str__() here to avoid deprecation warning
        # when referencing exc.message
        exc_str = exc.__str__().lower()
        if "unsupported url protocol" in exc_str and isinstance(
            self.credentials, pygit2.Keypair
        ):
            log.error(
                "Unable to fetch SSH-based {0} remote '{1}'. "
                "You may need to add ssh:// to the repo string or "
                "libgit2 must be compiled with libssh2 to support "
                "SSH authentication.".format(self.role, self.id)
            )
        elif "authentication required but no callback set" in exc_str:
            log.error(
                "{0} remote '{1}' requires authentication, but no "
                "authentication configured".format(self.role, self.id)
            )
        else:
            log.error(
                "Error occured fetching {0} remote '{1}': {2}".format(
                    self.role, self.id, exc
                )
            )
        return False
    try:
        # pygit2.Remote.fetch() returns a dict in pygit2 < 0.21.0
        received_objects = fetch_results["received_objects"]
    except (AttributeError, TypeError):
        # pygit2.Remote.fetch() returns a class instance in
        # pygit2 >= 0.21.0
        received_objects = fetch_results.received_objects
    if received_objects != 0:
        log.debug(
            "{0} received {1} objects for remote '{2}'".format(
                self.role, received_objects, self.id
            )
        )
    else:
        log.debug("{0} remote '{1}' is up-to-date".format(self.role, self.id))
    refs_post = self.repo.listall_references()
    cleaned = self.clean_stale_refs(local_refs=refs_post)
    return bool(received_objects or refs_pre != refs_post or cleaned)


# Traceback (TypeError)
[root@saltminion1 ~]# salt-minion -ldebug
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] Configuration file path: /etc/salt/minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[INFO    ] Setting up the Salt Minion "minion1"
[DEBUG   ] Created pidfile: /var/run/salt-minion.pid
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] The `lspci` binary is not available on the system. GPU grains will not be available.
[WARNING ] IMPORTANT: Do not use md5 hashing algorithm! Please set "hash_type" to sha256 in Salt Minion config!
[INFO    ] The Salt Minion is starting up
[INFO    ] Minion is starting as user 'root'
[DEBUG   ] AsyncEventPublisher PUB socket URI: ipc:///var/run/salt/minion/minion_event_c5a7daa544_pub.ipc
[DEBUG   ] AsyncEventPublisher PULL socket URI: ipc:///var/run/salt/minion/minion_event_c5a7daa544_pull.ipc
[INFO    ] Starting pub socket on ipc:///var/run/salt/minion/minion_event_c5a7daa544_pub.ipc
[INFO    ] Starting pull socket on ipc:///var/run/salt/minion/minion_event_c5a7daa544_pull.ipc
[DEBUG   ] Minion 'minion1' trying to tune in
[INFO    ] Got list of available master addresses: ['192.168.50.11', '192.168.50.12']
[DEBUG   ] Initializing new AsyncAuth for ('/etc/salt/pki/minion', 'minion1', 'tcp://192.168.50.11:4506')
[DEBUG   ] Generated random reconnect delay between '1000ms' and '11000ms' (8729)
[DEBUG   ] Setting zmq_reconnect_ivl to '8729ms'
[DEBUG   ] Setting zmq_reconnect_ivl_max to '11000ms'
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/minion', 'minion1', 'tcp://192.168.50.11:4506', 'clear')
[INFO    ] Master 192.168.50.11 could not be reached, trying next master (if any)
[WARNING ] Master ip address changed from 192.168.50.11 to 192.168.50.12
[DEBUG   ] Initializing new AsyncAuth for ('/etc/salt/pki/minion', 'minion1', 'tcp://192.168.50.12:4506')
[DEBUG   ] Generated random reconnect delay between '1000ms' and '11000ms' (10183)
[DEBUG   ] Setting zmq_reconnect_ivl to '10183ms'
[DEBUG   ] Setting zmq_reconnect_ivl_max to '11000ms'
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/minion', 'minion1', 'tcp://192.168.50.12:4506', 'clear')
[INFO    ] Master 192.168.50.12 could not be reached, trying next master (if any)
[ERROR   ] No master could be reached or all masters denied the minions connection attempt.
[INFO    ] The Salt Minion is shut down
[WARNING ] /usr/lib/python2.7/site-packages/salt/scripts.py:83: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
log.error('Minion failed to start: {0}'.format(exc.message), exc_info=True)

[ERROR   ] Minion failed to start: 'NoneType' object is not iterable
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/scripts.py", line 81, in minion_process
minion.start()
File "/usr/lib/python2.7/site-packages/salt/cli/daemons.py", line 320, in start
self.minion.tune_in()
File "/usr/lib/python2.7/site-packages/salt/minion.py", line 1699, in tune_in
self.sync_connect_master()
File "/usr/lib/python2.7/site-packages/salt/minion.py", line 760, in sync_connect_master
raise six.reraise(*future_exception)
File "/usr/lib64/python2.7/site-packages/tornado/gen.py", line 879, in run
yielded = self.gen.send(value)
File "/usr/lib/python2.7/site-packages/salt/minion.py", line 767, in connect_master
master, self.pub_channel = yield self.eval_master(self.opts, self.timeout, self.safe)
TypeError: 'NoneType' object is not iterable
[WARNING ] ** Restarting minion **
[INFO    ] Sleeping random_reauth_delay of 8 seconds
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] Configuration file path: /etc/salt/minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[INFO    ] Setting up the Salt Minion "minion1"
[DEBUG   ] Created pidfile: /var/run/salt-minion.pid
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] The `lspci` binary is not available on the system. GPU grains will not be available.
[WARNING ] IMPORTANT: Do not use md5 hashing algorithm! Please set "hash_type" to sha256 in Salt Minion config!
[INFO    ] The Salt Minion is starting up

# Fixed code
def _fetch(self):
    """
    Fetch the repo. If the local copy was updated, return True. If the
    local copy was already up-to-date, return False.
    """
    origin = self.repo.remotes[0]
    refs_pre = self.repo.listall_references()
    fetch_kwargs = {}
    if self.credentials is not None:
        if self.use_callback:
            fetch_kwargs["callbacks"] = pygit2.RemoteCallbacks(
                credentials=self.credentials
            )
        else:
            origin.credentials = self.credentials
    try:
        fetch_results = origin.fetch(**fetch_kwargs)
    except GitError as exc:
        exc_str = get_error_message(exc).lower()
        if "unsupported url protocol" in exc_str and isinstance(
            self.credentials, pygit2.Keypair
        ):
            log.error(
                "Unable to fetch SSH-based {0} remote '{1}'. "
                "You may need to add ssh:// to the repo string or "
                "libgit2 must be compiled with libssh2 to support "
                "SSH authentication.".format(self.role, self.id)
            )
        elif "authentication required but no callback set" in exc_str:
            log.error(
                "{0} remote '{1}' requires authentication, but no "
                "authentication configured".format(self.role, self.id)
            )
        else:
            log.error(
                "Error occured fetching {0} remote '{1}': {2}".format(
                    self.role, self.id, exc
                )
            )
        return False
    try:
        # pygit2.Remote.fetch() returns a dict in pygit2 < 0.21.0
        received_objects = fetch_results["received_objects"]
    except (AttributeError, TypeError):
        # pygit2.Remote.fetch() returns a class instance in
        # pygit2 >= 0.21.0
        received_objects = fetch_results.received_objects
    if received_objects != 0:
        log.debug(
            "{0} received {1} objects for remote '{2}'".format(
                self.role, received_objects, self.id
            )
        )
    else:
        log.debug("{0} remote '{1}' is up-to-date".format(self.role, self.id))
    refs_post = self.repo.listall_references()
    cleaned = self.clean_stale_refs(local_refs=refs_post)
    return bool(received_objects or refs_pre != refs_post or cleaned)