# Buggy code
def process_message(self, message):
    message_type, payload = decode_msg(message)
    if message_type in self.ordered_messages:
        chan_id = payload.get("channel_id") or payload["temporary_channel_id"]
        self.ordered_message_queues[chan_id].put_nowait((message_type, payload))
    else:
        if message_type != "error" and "channel_id" in payload:
            chan = self.get_channel_by_id(payload["channel_id"])
            if chan is None:
                raise Exception("Got unknown " + message_type)
            args = (chan, payload)
        else:
            args = (payload,)
        try:
            f = getattr(self, "on_" + message_type)
        except AttributeError:
            # self.logger.info("Received '%s'" % message_type.upper(), payload)
            return
        # raw message is needed to check signature
        if message_type in [
            "node_announcement",
            "channel_announcement",
            "channel_update",
        ]:
            payload["raw"] = message
        execution_result = f(*args)
        if asyncio.iscoroutinefunction(f):
            asyncio.ensure_future(execution_result)


# Traceback (AttributeError)
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | <<< send init {'gflen': 0, 'globalfeatures': b'', 'flen': 2, 'features': b' \x02', 'init_tlvs': {'networks': {'chains': b'CI\x7f\xd7\xf8&amp;\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00'}}}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | >>> recv init {'gflen': 2, 'globalfeatures': b'"\x00', 'flen': 3, 'features': b'\x02\xa2\xa1', 'init_tlvs': {}}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | <<< send channel_reestablish {'channel_id': b"\xc4\x02-\xd2\xa8s\xc8\xc1\xb4\xa9w\xf5a\xe03m\xa8\xcf'%\xd5\x02\xcf\xac\x8c;L\xeb\x1bU\xad\xca", 'next_commitment_number': 0, 'next_revocation_number': 0, 'your_last_per_commitment_secret': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'my_current_per_commitment_point': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | >>> recv channel_reestablish {'channel_id': b'\xab\xbf\xac2\x86.\xab\xa45\xa0\xa5\xad&amp;\na\xe5\xfd\xa1\xcbYL3\xa5\xeaR7\x86\xf3>\xf6\xd7C', 'next_commitment_number': 1, 'next_revocation_number': 0, 'your_last_per_commitment_secret': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'my_current_per_commitment_point': b'\x02|\xd7\xad\xf8\xe4\xe6\x97\xdcD/\xd3\xb2\xecC\x1c\xff\xad\x13ju\xa6\xb2\xd3\x06j\xda\x82b$Q\xfbU'}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | >>> recv channel_update {'signature': b'\xda[\xa8B\x8f&amp;Rq\\\xf2\x8by\x8c\xe1o\xb4\xf0,$1\x9a\xd8\x9b\xe1\x0c\xb7\xfa\x12\xf2\x16\x01@Z\xfe\xefF\x05\x15g\x14cz\xd5\xee\xcd\xf2(p\xb4\x86y\xa3\x99n\x00!\x91\x83\xfe\x82bxK\x87', 'chain_hash': b'CI\x7f\xd7\xf8&amp;\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00', 'short_channel_id': b'\x1b\n\xdb\x00\x00"\x00\x01', 'timestamp': 1592538360, 'message_flags': b'\x01', 'channel_flags': b'\x01', 'cltv_expiry_delta': 40, 'htlc_minimum_msat': 1000, 'fee_base_msat': 1000, 'fee_proportional_millionths': 1, 'htlc_maximum_msat': 10000000000}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | >>> recv channel_update {'signature': b'\x84"uT\x9b\\\x9c\x84\xffI\xce]R\xd6\xfa\xcd\xaf_\xbd\x8b}\xee\x82\xf7/\rGU\xe9[\xbeY\'\x82\x15 \t\xb3\xfc^#z\xb9\x01\xe9\xf3#\xc5p\xed=\x7f\xb4\x98\x13\xfdUT\xe7l\x05 \xd4*', 'chain_hash': b'CI\x7f\xd7\xf8&amp;\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00', 'short_channel_id': b'\x1b\n\xf0\x00\x00\x0b\x00\x00', 'timestamp': 1592542201, 'message_flags': b'\x01', 'channel_flags': b'\x03', 'cltv_expiry_delta': 40, 'htlc_minimum_msat': 1000, 'fee_base_msat': 1000, 'fee_proportional_millionths': 1, 'htlc_maximum_msat': 250000000}
I/P | lnpeer.Peer.[LNBackups, 92.53.89.123:19735] | >>> recv announcement_signatures {'channel_id': b"\xc4\x02-\xd2\xa8s\xc8\xc1\xb4\xa9w\xf5a\xe03m\xa8\xcf'%\xd5\x02\xcf\xac\x8c;L\xeb\x1bU\xad\xca", 'short_channel_id': b'\x1b\n\xf0\x00\x00\x0b\x00\x00', 'node_signature': b']*\xc3\xc7\xf7\xc7F\x80\xb8\xed7\xe8wd\xa4]\xaa\xddk\xc2y"\x0e\xd2\xdb\xdd\xbc\x1b{;\xe3,/\x10\xa8\xbfp\x0e\xff\'\xceeE\xfeyE\xdd3\x1c\xa1\xa5\xa1\xe4\xb0&amp;*Z3\xc3 \xafLBA', 'bitcoin_signature': b'\xf01\x8d\xa6Z\x1b\xfb\xf1\xf5`\xa3bG\x81o6W\x140w\xdasI\xccP \x9b\xcb\xe4\x92\xe1zX\x8dv\x07Ao\xebJ(q\x1f\x81B\x11\xd9\x9d\x92(\xaa\xe8\xa5h\xea[\xf1\x90\xde\x13+,,&amp;'}
E | lnworker.LNBackups | Exception in request_force_close: AttributeError("'LNBackups' object has no attribute 'get_channel_by_id'")
Traceback (most recent call last):
File "...\electrum\electrum\util.py", line 992, in wrapper
return await func(*args, **kwargs)
File "...\electrum\electrum\lnworker.py", line 1498, in request_force_close
await group.spawn(peer.trigger_force_close(channel_id))
File "...\aiorpcX\aiorpcx\curio.py", line 242, in __aexit__
await self.join()
File "...\aiorpcX\aiorpcx\curio.py", line 211, in join
raise task.exception()
File "...\electrum\electrum\lnpeer.py", line 482, in _message_loop
self.process_message(msg)
File "...\electrum\electrum\lnpeer.py", line 178, in process_message
chan = self.get_channel_by_id(payload['channel_id'])
File "...\electrum\electrum\lnpeer.py", line 155, in get_channel_by_id
chan = self.lnworker.get_channel_by_id(channel_id)
AttributeError: 'LNBackups' object has no attribute 'get_channel_by_id'
File "...\electrum\electrum\gui\qt\util.py", line 832, in run
result = task.task()
File "...\electrum\electrum\gui\qt\channels_list.py", line 141, in task
return self.network.run_from_another_thread(coro)
File "...\electrum\electrum\network.py", line 356, in run_from_another_thread
return fut.result(timeout)
File "...\Python38\lib\concurrent\futures\_base.py", line 439, in result
return self.__get_result()
File "...\Python38\lib\concurrent\futures\_base.py", line 388, in __get_result
raise self._exception
File "...\electrum\electrum\util.py", line 992, in wrapper
return await func(*args, **kwargs)
File "...\electrum\electrum\lnworker.py", line 1498, in request_force_close
await group.spawn(peer.trigger_force_close(channel_id))
File "...\aiorpcX\aiorpcx\curio.py", line 242, in __aexit__
await self.join()
File "...\aiorpcX\aiorpcx\curio.py", line 211, in join
raise task.exception()
File "...\electrum\electrum\lnpeer.py", line 482, in _message_loop
self.process_message(msg)
File "...\electrum\electrum\lnpeer.py", line 178, in process_message
chan = self.get_channel_by_id(payload['channel_id'])
File "...\electrum\electrum\lnpeer.py", line 155, in get_channel_by_id
chan = self.lnworker.get_channel_by_id(channel_id)

# Fixed code
def process_message(self, message):
    message_type, payload = decode_msg(message)
    # only process INIT if we are a backup
    from .lnworker import LNBackups

    if isinstance(self.lnworker, LNBackups) and message_type != "init":
        return
    if message_type in self.ordered_messages:
        chan_id = payload.get("channel_id") or payload["temporary_channel_id"]
        self.ordered_message_queues[chan_id].put_nowait((message_type, payload))
    else:
        if message_type != "error" and "channel_id" in payload:
            chan = self.get_channel_by_id(payload["channel_id"])
            if chan is None:
                raise Exception("Got unknown " + message_type)
            args = (chan, payload)
        else:
            args = (payload,)
        try:
            f = getattr(self, "on_" + message_type)
        except AttributeError:
            # self.logger.info("Received '%s'" % message_type.upper(), payload)
            return
        # raw message is needed to check signature
        if message_type in [
            "node_announcement",
            "channel_announcement",
            "channel_update",
        ]:
            payload["raw"] = message
        execution_result = f(*args)
        if asyncio.iscoroutinefunction(f):
            asyncio.ensure_future(execution_result)