netbirdio/netbird · error

parse peer key: %w

Error message

parse peer key: %w

What it means

WGUSPConfigurer.RemoveEndpointAddress could not parse the peer key with wgtypes.ParseKey, which requires a base64-encoded 32-byte key string. Any other encoding (notably the hex form used in wireguard-go UAPI lines), truncation, whitespace, or an empty string fails here before the IPC dump is read. It is the userspace twin of the parse error in the kernel configurer's RemoveAllowedIP.

Source

Thrown at client/iface/configurer/usp.go:135

	if ipcErr := c.device.IpcSet(toWgUserspaceString(config)); ipcErr != nil {
		return ipcErr
	}

	if endpoint != nil {
		addr, err := netip.ParseAddr(endpoint.IP.String())
		if err != nil {
			return fmt.Errorf("failed to parse endpoint address: %w", err)
		}
		addrPort := netip.AddrPortFrom(addr.Unmap(), uint16(endpoint.Port))
		c.activityRecorder.UpsertAddress(peerKey, addrPort)
	}
	return nil
}

func (c *WGUSPConfigurer) RemoveEndpointAddress(peerKey string) error {
	peerKeyParsed, err := wgtypes.ParseKey(peerKey)
	if err != nil {
		return fmt.Errorf("parse peer key: %w", err)
	}

	ipcStr, err := c.device.IpcGet()
	if err != nil {
		return fmt.Errorf("get IPC config: %w", err)
	}

	// Parse current status to get allowed IPs for the peer
	stats, err := parseStatus(c.deviceName, ipcStr)
	if err != nil {
		return fmt.Errorf("parse IPC config: %w", err)
	}

	var allowedIPs []net.IPNet
	found := false
	for _, peer := range stats.Peers {
		if peer.PublicKey == peerKey {
			allowedIPs = peer.AllowedIPs

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Validate once at ingestion with wgtypes.ParseKey and store key.String()
  2. Convert hex keys explicitly via hex.DecodeString + wgtypes.NewKey
  3. Trim whitespace and reject empty keys at the boundary that produces peer keys

Example fix

// before
err := cfg.RemoveEndpointAddress(hexKey)

// after
b, err := hex.DecodeString(hexKey)
if err != nil {
	return err
}
k, err := wgtypes.NewKey(b)
if err != nil {
	return err
}
err = cfg.RemoveEndpointAddress(k.String())
Defensive patterns

Strategy: validation

Validate before calling

// normalize the key before calling into the userspace configurer
parsed, err := wgtypes.ParseKey(peerKey)
if err != nil {
	return fmt.Errorf("bad peer key from upstream: %w", err)
}
return uspCfg.RemoveEndpointAddress(parsed.String())

Type guard

func isValidWGPeerKey(s string) bool {
	_, err := wgtypes.ParseKey(s)
	return err == nil
}

Try / catch

if err := uspCfg.RemoveEndpointAddress(peerKey); err != nil {
	if _, perr := wgtypes.ParseKey(peerKey); perr != nil {
		// producer bug: fix key format at source, retrying will not help
		return fmt.Errorf("peer key malformed upstream: %w", perr)
	}
	return err
}

Prevention

When it happens

Trigger: Hex-encoded peer key passed where base64 is expected; key copied from a public_key=<hex> UAPI line; empty or truncated key from an upstream payload; whitespace or newline appended to the key.

Common situations: Sharing key strings between kernel-mode and userspace-mode code paths without format conversion; management or test fixtures supplying malformed keys; keys logged and re-read with formatting artifacts.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/3020eded88cac40f. Report an issue: GitHub.