VPNSmith
self-host-vpnINFO

WireGuard: Key Is Not the Correct Length or Format

A WireGuard key is 32 bytes written as 44 base64 characters ending in an equals sign. The error means what you pasted is not that, and the cause is almost always invisible: a trailing newline, a wrapped line, a key echoed with a shell prompt, or a public key sitting where a private one belongs.

By Eric Gerard · Founder · VPNSmith - Self-host VPN & GDPR VPS specialist4 min readPhoto via Pexels

Affiliate disclosure - This post contains Contabo affiliate links. If you grab a VPS through them, we earn a commission at no extra cost to you.

You start the interface and get stopped before anything connects:

Key is not the correct length or format

The key on screen looks fine. That is the whole difficulty with this error: the thing that is wrong is usually a character you cannot see.

What a valid key is, exactly

A WireGuard key is 32 bytes of raw data. Written in base64, 32 bytes is exactly 44 characters, and the last one is always =, the padding character. That gives you a test you can apply in a second, by eye or by command:

echo -n "$KEY" | wc -c

44 with no newline, 45 if the newline is still attached. Anything else is not a key, whatever it looks like.

The same statement applies to private keys, public keys and preshared keys, since all three are 32 bytes. Which leads directly to the trap in the last section.

Cause 1: an invisible trailing newline

The most common single cause, and it comes from a command that looks entirely reasonable:

PRIVATE_KEY=$(cat privatekey)

cat returns the file including its trailing newline, and command substitution here does strip it, but the same value written into a config with a heredoc or an editor macro often keeps it. Written into wg0.conf, you get a key followed by a stray character and a 45 byte value where 44 was required.

Strip it explicitly rather than hoping:

tr -d '\n' < privatekey

Cause 2: the key wrapped across two lines

Copying a key out of a narrow terminal window, an email, or a chat client can insert a line break in the middle of it. In the config file the value now ends after 30-odd characters, and the rest sits on its own orphan line.

Look for it with a length check per line rather than reading:

awk -F' = ' '/Key/ {print $1, length($2)}' /etc/wireguard/wg0.conf

Every key line should print 44. Anything else on that list is your culprit, and this works on a config with a dozen peers where inspecting by eye does not.

A white paper measuring tape curled into a loop on a black background, showing the numbers 29 to 45 with fine millimetre graduations between them
A white paper measuring tape curled into a loop on a black background, showing the numbers 29 to 45 with fine millimetre graduations between them

Cause 3: the key came with company

A key generated and displayed in one step can pick up things around it. Two versions of this:

  • A shell prompt or command echo captured along with the output when copying from a scrollback buffer.
  • A leading space, which base64 does not tolerate and which no editor will show you.

Regenerating is faster than forensics when it is a fresh key:

wg genkey > privatekey
chmod 600 privatekey
wg pubkey < privatekey > publickey

Redirecting into a file rather than reading it off the screen removes the whole category of problem, and the chmod matters because a private key readable by everyone is its own issue.

Cause 4: the right kind of key in the wrong slot

This one does not produce the error, and that is precisely why it belongs here. A public key is also 44 base64 characters, so putting one in the PrivateKey field parses perfectly and fails silently forever. No message, no rejection, just a handshake that never happens.

The check is to derive rather than compare:

wg pubkey < privatekey

If the output equals the value in your PrivateKey field, you have put a public key there. A private key run through wg pubkey gives you something different from itself; a public key run through it gives garbage or an error, never the value you started from.

A one line audit of every key in a config

Instead of testing them one at a time:

grep -oP '(?<= = )[A-Za-z0-9+/]{40,50}=' /etc/wireguard/wg0.conf | while read k; do
  printf '%s %s\n' "$(printf %s "$k" | wc -c)" "$k"
done

Every line should begin with 44. A number that is not 44 is a broken key, and you have found it without reading a single character of base64.

Where this shows up next

Fixing the format gets you past the parse and into the next class of problem, which is a tunnel that comes up and does nothing. A key that is well formed but not the key the other end expects produces a different failure entirely, covered in the required key not available error.

Two adjacent cases are worth separating from this one. The preshared key is a third key with the same 44 character shape but symmetric rules, so it is easy to misplace: see the preshared key guide. And the same key installed on two devices parses fine and breaks in a way that looks random, which is a separate story in two devices, one key.

If you are writing configs by hand often enough to hit this repeatedly, the templates in WireGuard config templates remove most of the transcription.

★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed

Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region

Frequently asked questions

How long is a WireGuard key supposed to be?
A key is 32 bytes of raw data, which base64 encodes to exactly 44 characters, the last of which is an equals sign used as padding. Anything shorter, longer, or lacking that trailing equals sign will be rejected before the tunnel is attempted.
Why does my key look right but still get rejected?
Because the defect is usually whitespace you cannot see. A key captured with command substitution keeps its trailing newline, a key pasted from a wrapped terminal picks up a line break in the middle, and both look identical to a correct key on screen.
Can I use a public key where a private key goes?
The file will parse, because both are 44 base64 characters and structurally indistinguishable. It will simply never handshake, which makes this the worst version of the mistake: no error at all, just a tunnel that stays silent.
Does the error tell me which key is wrong?
Not reliably. wg reports the line it choked on in some versions and only the general failure in others, so on a config with several peers the practical approach is to measure every key with a one line loop rather than inspect them by eye.
How do I check a key without eyeballing it?
Pipe it to wc -c and expect 45 for a key with its newline, or 44 without. Better still, feed it to wg pubkey: a valid private key produces a public key, and an invalid one produces the same length error, which turns the check into a yes or no.