netbirdio/netbird · error
failed to remove interface %s: %w - %s
Error message
failed to remove interface %s: %w - %s
What it means
The BSD (darwin/dragonfly/freebsd/netbsd/openbsd) implementation of WGIface.Destroy() runs `ifconfig <name> destroy` and wraps failure with both the exec error and the raw combined output for diagnosis. It fails when the interface does not exist, is busy, or the process lacks privileges; note this path uses raw exec on all BSDs including macOS, not the freebsd Link helper.
Source
Thrown at client/iface/iface_destroy_bsd.go:13
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
package iface
import (
"fmt"
"os/exec"
)
func (w *WGIface) Destroy() error {
out, err := exec.Command("ifconfig", w.Name(), "destroy").CombinedOutput()
if err != nil {
return fmt.Errorf("failed to remove interface %s: %w - %s", w.Name(), err, out)
}
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Run the same command by hand to see the exact refusal: `sudo ifconfig <name> destroy`
- Treat a missing interface as success in the caller
- Ensure the daemon runs privileged
- Clear addresses/routes on the interface before destroying
Example fix
// before
func (w *WGIface) Destroy() error {
out, err := exec.Command("ifconfig", w.Name(), "destroy").CombinedOutput()
if err != nil {
return fmt.Errorf("failed to remove interface %s: %w - %s", w.Name(), err, out)
}
return nil
}
// after: idempotent destroy
func (w *WGIface) Destroy() error {
if _, lerr := net.InterfaceByName(w.Name()); lerr != nil {
return nil // already gone
}
out, err := exec.Command("ifconfig", w.Name(), "destroy").CombinedOutput()
if err != nil {
return fmt.Errorf("failed to remove interface %s: %w - %s", w.Name(), err, out)
}
return nil
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := net.InterfaceByName(name); err != nil {
return nil // nothing to destroy
} Try / catch
if err := w.Destroy(); err != nil {
if _, lerr := net.InterfaceByName(w.Name()); lerr != nil {
return nil // gone: success
}
return err
} Prevention
- Make destroy idempotent by checking existence first
- Read the embedded ifconfig output in the message: it names the real refusal
- Run netbird down before manual interface surgery
When it happens
Trigger: Close()'s fallback after waitUntilRemoved() timed out; destroying an interface that already vanished; running the daemon unprivileged; interface still referenced by routes or bridge membership.
Common situations: macOS agent where the interface already disappeared; double teardown; stale interface held by addresses or routes.
Related errors
- destroy %s interface: %w
- invalid interface name %s. Please use the prefix utun follow
- up: %w
- link by name: %w
- assign addr: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/56c88144d7fab4de.
Report an issue: GitHub.