"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
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
wg show— has a handshake ever succeeded?- Try the same config on a different network, ideally mobile data. If it works there, the first network blocks UDP.
- Verify the public key on both sides.
- Bring the interface down and up to re-resolve the endpoint.
- Check the system clock.
- 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.