netbirdio/netbird · error

peer %s not found

Error message

peer %s not found

What it means

WGUSPConfigurer.RemoveEndpointAddress scanned the parsed IPC dump for the peer's public key and found no match, so there is no endpoint to clear. The peer must already exist in the userspace device's live state for this operation to make sense. Typically the peer was already removed (or never added) by the time the call ran.

Source

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

	}

	// 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
			found = true
			break
		}
	}
	if !found {
		return fmt.Errorf("peer %s not found", peerKey)
	}

	// remove the peer from the WireGuard configuration
	peer := wgtypes.PeerConfig{
		PublicKey: peerKeyParsed,
		Remove:    true,
	}

	config := wgtypes.Config{
		Peers: []wgtypes.PeerConfig{peer},
	}
	if ipcErr := c.device.IpcSet(toWgUserspaceString(config)); ipcErr != nil {
		return fmt.Errorf("failed to remove peer: %s", ipcErr)
	}

	// Build the peer config
	peer = wgtypes.PeerConfig{
		PublicKey:         peerKeyParsed,

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Treat a missing peer as success: there is no endpoint left to remove
  2. Call RemoveEndpointAddress before RemovePeer in teardown sequences
  3. Re-check with FullStats if you need to distinguish 'already gone' from a key-format mismatch
  4. Guard concurrent peer mutations with a lock so removal and endpoint clearing cannot interleave

Example fix

// before
if !found {
	return fmt.Errorf("peer %s not found", peerKey)
}

// after: clearing the endpoint of an absent peer is a no-op
if !found {
	return nil
}
Defensive patterns

Strategy: validation

Validate before calling

// confirm the peer exists before clearing its endpoint
stats, err := uspCfg.FullStats()
if err != nil {
	return err
}
for _, p := range stats.Peers {
	if p.PublicKey == peerKey {
		return uspCfg.RemoveEndpointAddress(peerKey)
	}
}
return nil // peer absent: nothing to clear

Try / catch

if err := uspCfg.RemoveEndpointAddress(peerKey); err != nil {
	if strings.Contains(err.Error(), "not found") {
		// already removed: idempotent success
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: RemoveEndpointAddress called after RemovePeer; network-map update removed the peer concurrently; peer key string in a different format than the one stored (base64 vs the parsed stats' base64 form); peer never added because connection setup failed earlier.

Common situations: Connection-close handler racing a management update that drops the peer; teardown code clearing endpoints for all peers after mass removal; embedded client shutdown ordering.

Related errors


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