From 4556d59fc0f2005a26b73344b5026c009a094941 Mon Sep 17 00:00:00 2001 From: f321x Date: Mon, 16 Feb 2026 09:28:16 +0100 Subject: [PATCH] plugin: nwc: qt: fix thread safety bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call `NWCServer.event_handler_task.cancel()` on asyncio thread. ```  File "/home/user/Documents/electrum/electrum/plugins/nwc/nwcserver.py", line 281, in restart_event_handler    self.event_handler_task.cancel()    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^  File "/usr/lib64/python3.14/asyncio/base_events.py", line 829, in call_soon    self._check_thread()    ~~~~~~~~~~~~~~~~~~^^  File "/usr/lib64/python3.14/asyncio/base_events.py", line 866, in _check_thread    raise RuntimeError(        "Non-thread-safe operation invoked on an event loop other "        "than the current one") RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one ``` --- electrum/plugins/nwc/nwcserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/electrum/plugins/nwc/nwcserver.py b/electrum/plugins/nwc/nwcserver.py index 7823b3380..112859ccf 100644 --- a/electrum/plugins/nwc/nwcserver.py +++ b/electrum/plugins/nwc/nwcserver.py @@ -39,7 +39,7 @@ from electrum.plugin import BasePlugin, hook from electrum.logging import Logger from electrum.util import log_exceptions, ca_path, OldTaskGroup, get_asyncio_loop, InvoiceError, \ LightningHistoryItem, event_listener, EventListener, make_aiohttp_proxy_connector, \ - get_running_loop + get_running_loop, run_sync_function_on_asyncio_thread from electrum.invoices import Invoice, Request, PR_UNKNOWN, PR_PAID, BaseInvoice, PR_INFLIGHT from electrum import constants from electrum.lnutil import RECEIVED @@ -278,7 +278,7 @@ class NWCServer(Logger, EventListener): def restart_event_handler(self) -> None: """To be called when the connections change so we restart with a new filter""" if self.event_handler_task: - self.event_handler_task.cancel() + run_sync_function_on_asyncio_thread(self.event_handler_task.cancel, block=True) @event_listener def on_event_proxy_set(self, *args):