Skip to content

remove_connection_async: future never resolved on successful delete → TimeoutError crash on startup #7

Description

@YoshKoz

Environment

  • App: proton-vpn-gtk-app 4.16.4
  • Package: python-proton-vpn-network-manager (latest Arch/AUR)
  • Python: 3.14.5
  • NetworkManager: 1.56.1
  • OS: Arch Linux (CachyOS)

Bug Description

On startup, protonvpn-app crashes with asyncio.exceptions.TimeoutError before the window appears.

Root cause is in killswitch/wireguard/nmclient.py — the _on_connection_removed callback calls connection.delete_finish(result) on success but never calls future_interface_removed.set_result(None). The future can only be resolved via the device-removed GLib signal. When no WireGuard kill switch interface is active (e.g. after reboot, or after manually deleting stale pvpn-killswitch-perm NM connections), that signal never fires and the 10-second asyncio timeout in _wrap_future triggers.

This affects both killswitch=2 (permanent, tries to enable) and killswitch=0 (disabled, tries to remove) on startup.

Traceback

File "/usr/bin/protonvpn-app", line 8, in <module>
    sys.exit(main())
File ".../proton/vpn/app/gtk/__main__.py", line 35, in main
    controller = Controller.get(executor, exception_handler)
File ".../proton/vpn/app/gtk/controller.py", line 74, in get
    executor.submit(controller.initialize_vpn_connector).result()
File ".../proton/vpn/core/vpnconnector.py", line 288, in initialize_state
    await self._update_state(state)
File ".../proton/vpn/connection/states.py", line 196, in run_tasks
    await self.context.kill_switch.disable()
File ".../killswitch/wireguard/wgkillswitch.py", line 76, in disable
    await self._ks_handler.remove_killswitch_connection()
File ".../killswitch/wireguard/killswitch_connection_handler.py", line 291, in _remove_connection
    await _wrap_future(self.nm_client.remove_connection_async(connection))
File ".../killswitch/wireguard/killswitch_connection_handler.py", line 56, in _wrap_future
    return await asyncio.wait_for(...)
asyncio.exceptions.TimeoutError

Affected Code

killswitch/wireguard/nmclient.py, remove_connection_async method:

def _on_connection_removed(connection, result, _user_data):
    try:
        connection.delete_finish(result)
        # BUG: future_interface_removed.set_result(None) is never called on success.
        # Future only resolves via device-removed signal, which never fires
        # if no WireGuard interface is currently active.
    except Exception as exc:
        future_interface_removed.set_exception(...)

Proposed Fix

def _on_connection_removed(connection, result, _user_data):
    try:
        connection.delete_finish(result)
        if not future_interface_removed.done():
            future_interface_removed.set_result(None)  # resolve on success
    except Exception as exc:
        future_interface_removed.set_exception(...)

Steps to Reproduce

  1. Have killswitch set to 0 or 2 in ~/.config/Proton/VPN/settings.json
  2. Ensure no active pvpnksintrf1 WireGuard interface exists (fresh boot or after removing stale NM connections)
  3. Launch protonvpn-app — crashes immediately with TimeoutError

Workaround

None currently available without patching the source or downgrading Python.


Bug reported via automated analysis using Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions