netbirdio/netbird · error

failed to remove interface %s: %w - %s

Error message

failed to remove interface %s: %w - %s

What it means

The Windows Destroy() disables (does not delete) the adapter via `netsh interface set interface <name> admin=disable`, locating netsh through GetSystem32Command, which falls back to C:\windows\system32 when PATH lookup fails. The error wraps the exec failure plus raw netsh output: interface name not found, netsh unavailable, or the process not elevated.

Source

Thrown at client/iface/iface_destroy_windows.go:16

//go:build windows

package iface

import (
	"fmt"
	"os/exec"

	log "github.com/sirupsen/logrus"
)

func (w *WGIface) Destroy() error {
	netshCmd := GetSystem32Command("netsh")
	out, err := exec.Command(netshCmd, "interface", "set", "interface", w.Name(), "admin=disable").CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to remove interface %s: %w - %s", w.Name(), err, out)
	}
	return nil
}

// GetSystem32Command checks if a command can be found in the system path and returns it. In case it can't find it
// in the path it will return the full path of a command assuming C:\windows\system32 as the base path.
func GetSystem32Command(command string) string {
	_, err := exec.LookPath(command)
	if err == nil {
		return command
	}

	log.Tracef("Command %s not found in PATH, using C:\\windows\\system32\\%s.exe path", command, command)

	return "C:\\windows\\system32\\" + command + ".exe"
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. List adapters with `netsh interface show interface` (or ncpa.cpl) and confirm the exact name spelling
  2. Repair the adapter by re-running netbird up
  3. Run the agent as an elevated service (LocalSystem is the default)
  4. Verify netsh resolves: `where netsh` and that C:\Windows\System32\netsh.exe exists
Defensive patterns

Strategy: try-catch

Validate before calling

ifaces, err := net.Interfaces()
if err == nil {
    for _, i := range ifaces {
        if i.Name == name {
            return nil // exists, safe to Destroy
        }
    }
    return nil // adapter already gone
}

Try / catch

if err := w.Destroy(); err != nil {
    if strings.Contains(err.Error(), "not found") {
        return nil // adapter no longer present
    }
    return err
}

Prevention

When it happens

Trigger: Destroy() when the wintun adapter name does not match (uninstalled, renamed, or created under a different name by another version), when netsh cannot execute from the fallback path, or when the process runs without elevation.

Common situations: Adapter removed by a driver uninstall/reinstall; interface renamed in configuration so netsh cannot find it; broken PATH or 32-on-64-bit System32 redirection; non-admin invocation.

Related errors


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