Skip to content
VPNmine
TROUBLESHOOTING

"Handshake did not complete": what the WireGuard error means

The message means your device sent handshake initiations and the server never replied, or its reply never arrived. Four causes account for nearly all of it: UDP blocked on the path, a key mismatch, an endpoint that no longer answers, and a device clock wrong enough to trip the replay defence.

4 min read

Illustration of a handshake and an hourglass, joined by a dashed tunnel line on a dark grid.

WireGuard's handshake is two messages. The client sends an initiation, the server sends a response, and after that both ends have session keys. "Handshake did not complete" means the first message went out and the second never came back. That is a small enough failure surface to enumerate completely.

First, look at wg show

sudo wg show

If there is no latest handshake line at all, no handshake has ever succeeded on this interface. If there is one but it is old and the transfer counters are not moving, a handshake succeeded once and renewal is now failing. The two point at different causes: never-succeeded is usually configuration or a blocked path, stopped-succeeding is usually the network or the clock.

Cause one: UDP is blocked

WireGuard is UDP only. It has no TCP mode, no port 443 fallback and no obfuscation in the protocol itself. A network that blocks outbound UDP, or blocks the specific port, blocks WireGuard completely and silently — there is no rejection, packets simply do not arrive.

This is standard on many corporate, campus and hotel networks, and it is the most common cause on a network where the same config works fine elsewhere.

Test it directly:

nc -u -z -v vpn.example.net 51820

A provider that offers an alternative port, or an OpenVPN endpoint over TCP 443, is the way through. Nothing about the WireGuard configuration will help.

Cause two: the keys do not match

The server has to know your public key, and your config has to carry the server's. A mismatch produces exactly this error, because the server cannot decrypt the initiation and correctly says nothing at all rather than revealing that it is there.

Check your public key matches what the server has:

wg show vpnmine public-key

Then check the [Peer] PublicKey in the config against what the provider published. If you regenerated keys on the device without re-registering, this is certainly it. If a preshared key is configured on one side and not the other, the same silence results.

Cause three: the endpoint no longer answers

Endpoint is resolved once, at interface bring-up. If it is a hostname and the address behind it has changed since, or the server has moved or is down, your initiations are going somewhere that does not answer.

Bring the interface down and up again to re-resolve. If the config uses a bare IP address and the server has moved, only a new config fixes it.

If your provider rotates endpoints, a hostname is the more robust choice — with the caveat that a config which also sets the tunnel's DNS needs to resolve that hostname before the resolver changes, which wg-quick handles but a hand-rolled setup may not.

Cause four: the clock is wrong

WireGuard's handshake carries a TAI64N timestamp, and a peer rejects any initiation whose timestamp is not greater than the last one it accepted from that key. That is the replay defence described in the protocol documentation.

A device whose clock is significantly ahead can therefore poison itself: it sends an initiation stamped in the future, the server records it, and every subsequent correctly-stamped message is rejected as old. A device whose clock is behind fails in the more obvious direction.

Turn automatic time-setting on. Minutes of drift are fine; hours are not.

Cause five, less common: MTU on the handshake path

Rare but real. Handshake messages are small, so MTU rarely blocks them, but a path that fragments UDP and drops fragments will drop them. If handshakes succeed on one network and never on another, and UDP is definitely allowed, lowering the MTU is worth one attempt.

Cause six: rate limiting

WireGuard servers under load use a cookie mechanism to shed handshake floods. A client reconnecting in a tight loop can trip it and be ignored for a period. Stop the interface, wait a minute, and start it once rather than repeatedly.

The order to work through

  1. wg show — has a handshake ever succeeded?
  2. Try the same config on a different network, ideally mobile data. If it works there, the first network blocks UDP.
  3. Verify the public key on both sides.
  4. Bring the interface down and up to re-resolve the endpoint.
  5. Check the system clock.
  6. Try a different server, which rules out one server being down.

If it works on mobile data and not on a specific Wi-Fi network, stop troubleshooting the configuration. The configuration is correct and the network is the obstacle.

Sources

  1. WireGuard — protocol and cryptography
  2. WireGuard: Next Generation Kernel Network Tunnel (NDSS 2017)
  3. RFC 768 — User Datagram Protocol

Try it on the network this was written from

VPNmine is a free no-logs VPN running its own WireGuard servers, with native apps for Windows, macOS, Android, iOS, Android TV and Apple TV. No ads, no card.

Get VPNmine