[GH-ISSUE #2787] amnezia vpn enters a reconnect loop after wi-fi roaming on macos #1271

Open
opened 2026-10-13 20:39:15 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @ppoult on GitHub (Jun 30, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2787

Environment

macos 26.2, build 25C56
apple silicon, arm64
amnezia vpn 4.8.19
the application binaries are x86_64 and run through rosetta
full-tunnel wireguard/amneziawg connection
wi-fi network with multiple access points

Actual behavior

When macos roams between two access points with the same ssid, amnezia vpn immediately enters a reconnect loop. The wireguard-go process is restarted and all network connections are interrupted.

11:22:43.793 wi-fi: APPLE80211_M_ROAMED
11:22:43.888 wi-fi: roamed between access points on channel 48
11:22:44.246 amnezia vpn: Reconnect triggered on Reconnecting during inappropriate state; ignoring slot
11:22:44 wireguard-go process restarted

The reconnect message is repeated dozens of times.
During one reconnect, packet loss through the vpn reached 38%, while packet loss to the local router remained 0%. mtu tests and repeated https requests work normally between reconnects.

No system proxy is configured, other vpn clients are disconnected, and third-party network filtering is disabled.

Expected behavior

The vpn should remain connected or perform a normal handshake after wi-fi roaming without restarting wireguard-go or interrupting active connections.

Additional information

The same wi-fi network works normally on a phone. The problem appears specific to the macos client’s handling of network-path changes.

Originally created by @ppoult on GitHub (Jun 30, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2787 ### **Environment** macos 26.2, build 25C56 apple silicon, arm64 amnezia vpn 4.8.19 the application binaries are x86_64 and run through rosetta full-tunnel wireguard/amneziawg connection wi-fi network with multiple access points ### Actual behavior When macos roams between two access points with the same ssid, amnezia vpn immediately enters a reconnect loop. The wireguard-go process is restarted and all network connections are interrupted. ``` 11:22:43.793 wi-fi: APPLE80211_M_ROAMED 11:22:43.888 wi-fi: roamed between access points on channel 48 11:22:44.246 amnezia vpn: Reconnect triggered on Reconnecting during inappropriate state; ignoring slot 11:22:44 wireguard-go process restarted ``` The reconnect message is repeated dozens of times. During one reconnect, packet loss through the vpn reached 38%, while packet loss to the local router remained 0%. mtu tests and repeated https requests work normally between reconnects. No system proxy is configured, other vpn clients are disconnected, and third-party network filtering is disabled. ### Expected behavior The vpn should remain connected or perform a normal handshake after wi-fi roaming without restarting wireguard-go or interrupting active connections. ### Additional information The same wi-fi network works normally on a phone. The problem appears specific to the macos client’s handling of network-path changes.
Author
Owner

@dantetemp commented on GitHub (Sep 15, 2026):

Confirming this on a much newer build, with server-side evidence that pins down what happens after the reconnect loop starts.

Environment: AmneziaVPN 5.0.1.5 (7d4f3e0), macOS Tahoe 26.3, Apple Silicon (native), self-hosted AmneziaWG 3.1 (amneziawg-tools v3.1.20260812), full tunnel. So this is not limited to 4.8.x or to AmneziaWG 2.0.

I captured two consecutive occurrences with client logs, service logs, and the server polled every 15 s via wg show dump.

Occurrence 1 — 22:22:53 → 22:27:51 UTC (~5 min)

22:22:53.080  MacOSNetworkWatcher : BSSID changed! en0
22:22:53.257  MacOSNetworkWatcher : Found active WiFi connection on en0 SSID: None Security: None
22:22:53.266  Reconnect triggered. Reconnecting to the server
22:22:53.273  Connection state: 'Disconnected'
   -> 35 x "Reconnect triggered on Reconnecting during inappropriate state: %2; ignoring slot"
      in 6 bursts at 22:22:53, 22:22:56, 22:23:02, 22:23:03, 22:23:41, 22:23:42
22:23:49.208  Handshake completed with: <server pubkey>
22:23:49.208  Connection state: 'Connected'

The UI then said Connected for ~3.5 minutes while the tunnel was dead. From the server, same window:

22:24:02  handshake_age=13s    rx=20932979780
22:25:32  handshake_age=103s
22:26:47  handshake_age=178s
22:27:33  handshake_age=224s   rx=20934656504  (frozen)

latest handshake never reset for 224 s, while RejectAfterTime is 150-180 s. The session was expired and could not carry traffic, yet the client reported Connected.

Recovery required three manual disconnect/connect presses (22:26:56, 22:27:38, 22:27:48). The first two produced more ignoring slot warnings and did nothing; only the third got through. Real handshake at 22:27:50.710.

Occurrence 2 — 22:44:01 → 22:44:39 UTC (~37 s)

22:44:01.317  MacOSNetworkWatcher : BSSID changed! en0
22:44:01.435  MacosRouteMonitor   : Lost default route via en0
22:44:02.056  MacOSNetworkWatcher : Found active WiFi connection on en0 SSID: <correct> Security: WPA2 Personal
22:44:02.056  Reconnect triggered. Reconnecting to the server
   -> 13 x "... inappropriate state ... ignoring slot" in a single burst
22:44:38.540  (manual press) "Trying to connect to VPN"
22:44:39.258  Handshake completed

Server side: at 22:44:23 and 22:44:38 the peer had already moved to a new endpoint, but handshake_age kept climbing (60 s, 75 s) and rx was frozen. It recovered only on the manual press, on a new source port.

Two things worth adding to the report:

  1. An empty SSID read is not required. In occurrence 2 the SSID was read correctly and the fault still happened. A BSSID change alone is enough to tear the tunnel down.
  2. The machine loses all internet, not just VPN, for the whole duration — until the app actually reaches the Disconnected state and restores routes. This makes waiting it out impossible.

Also note the %2 placeholder in that warning is never substituted, so the offending state name is lost from the logs.

Probably the same defect, different triggers: #2972 (macOS, network down/up and sleep/wake) quotes the identical ignoring slot line on 5.0.0.5, and #3110 describes the same "network-state transition causes an unnecessary full reconnect" logic on Linux. Windscribe/Desktop-App#307 reports the same same-SSID AP-roam teardown with AmneziaWG in a different client and argues it is client-side detection logic, not a protocol requirement — plain WireGuard roams without a rebuild.

Suggested fixes, in order of value:

  1. Do not tear the tunnel down on a BSSID change when SSID, server, protocol and port are unchanged.
  2. Do not discard reconnect requests while in Reconnecting — queue or coalesce them.
  3. Do not report Connected when no handshake has completed within RejectAfterTime.
  4. Substitute %2 so the state is visible in logs.

Full client and service logs plus the 15-second server-side samples are available if useful.

<!-- gh-comment-id:5689417294 --> @dantetemp commented on GitHub (Sep 15, 2026): Confirming this on a much newer build, with server-side evidence that pins down what happens after the reconnect loop starts. **Environment:** AmneziaVPN **5.0.1.5** (`7d4f3e0`), macOS Tahoe 26.3, Apple Silicon (native), self-hosted **AmneziaWG 3.1** (`amneziawg-tools v3.1.20260812`), full tunnel. So this is not limited to 4.8.x or to AmneziaWG 2.0. I captured two consecutive occurrences with client logs, service logs, and the server polled every 15 s via `wg show dump`. **Occurrence 1 — 22:22:53 → 22:27:51 UTC (~5 min)** ``` 22:22:53.080 MacOSNetworkWatcher : BSSID changed! en0 22:22:53.257 MacOSNetworkWatcher : Found active WiFi connection on en0 SSID: None Security: None 22:22:53.266 Reconnect triggered. Reconnecting to the server 22:22:53.273 Connection state: 'Disconnected' -> 35 x "Reconnect triggered on Reconnecting during inappropriate state: %2; ignoring slot" in 6 bursts at 22:22:53, 22:22:56, 22:23:02, 22:23:03, 22:23:41, 22:23:42 22:23:49.208 Handshake completed with: <server pubkey> 22:23:49.208 Connection state: 'Connected' ``` The UI then said **Connected for ~3.5 minutes while the tunnel was dead**. From the server, same window: ``` 22:24:02 handshake_age=13s rx=20932979780 22:25:32 handshake_age=103s 22:26:47 handshake_age=178s 22:27:33 handshake_age=224s rx=20934656504 (frozen) ``` `latest handshake` never reset for 224 s, while `RejectAfterTime` is 150-180 s. The session was expired and could not carry traffic, yet the client reported Connected. Recovery required **three manual disconnect/connect presses** (22:26:56, 22:27:38, 22:27:48). The first two produced more `ignoring slot` warnings and did nothing; only the third got through. Real handshake at 22:27:50.710. **Occurrence 2 — 22:44:01 → 22:44:39 UTC (~37 s)** ``` 22:44:01.317 MacOSNetworkWatcher : BSSID changed! en0 22:44:01.435 MacosRouteMonitor : Lost default route via en0 22:44:02.056 MacOSNetworkWatcher : Found active WiFi connection on en0 SSID: <correct> Security: WPA2 Personal 22:44:02.056 Reconnect triggered. Reconnecting to the server -> 13 x "... inappropriate state ... ignoring slot" in a single burst 22:44:38.540 (manual press) "Trying to connect to VPN" 22:44:39.258 Handshake completed ``` Server side: at 22:44:23 and 22:44:38 the peer had already moved to a new endpoint, but `handshake_age` kept climbing (60 s, 75 s) and `rx` was frozen. It recovered only on the manual press, on a new source port. **Two things worth adding to the report:** 1. **An empty SSID read is not required.** In occurrence 2 the SSID was read correctly and the fault still happened. A BSSID change alone is enough to tear the tunnel down. 2. **The machine loses all internet, not just VPN**, for the whole duration — until the app actually reaches the Disconnected state and restores routes. This makes waiting it out impossible. Also note the `%2` placeholder in that warning is never substituted, so the offending state name is lost from the logs. **Probably the same defect, different triggers:** #2972 (macOS, network down/up and sleep/wake) quotes the identical `ignoring slot` line on 5.0.0.5, and #3110 describes the same "network-state transition causes an unnecessary full reconnect" logic on Linux. Windscribe/Desktop-App#307 reports the same same-SSID AP-roam teardown with AmneziaWG in a different client and argues it is client-side detection logic, not a protocol requirement — plain WireGuard roams without a rebuild. **Suggested fixes, in order of value:** 1. Do not tear the tunnel down on a BSSID change when SSID, server, protocol and port are unchanged. 2. Do not discard reconnect requests while in `Reconnecting` — queue or coalesce them. 3. Do not report `Connected` when no handshake has completed within `RejectAfterTime`. 4. Substitute `%2` so the state is visible in logs. Full client and service logs plus the 15-second server-side samples are available if useful.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1271
No description provided.