netbirdio/netbird · error

error configuring interface: %s

Error message

error configuring interface: %s

What it means

Thrown by TunNetstackDevice.create() in netstack mode, where wireguard-go runs over a gVisor userspace stack with no OS tun device. After the device is constructed, WGUSPConfigurerNoUAPI.ConfigureInterface parses the WireGuard private key with wgtypes.ParseKey and applies private_key/listen_port/fwmark via device.IpcSet. This error wraps any failure of that step; the netstack tun is closed and create() returns nil.

Source

Thrown at client/iface/device/device_netstack.go:93

	if err != nil {
		return nil, fmt.Errorf("error creating tun device: %s", err)
	}
	t.filteredDevice = newDeviceFilter(tunIface)
	t.net = net

	t.device = device.NewDevice(
		t.filteredDevice,
		t.bind,
		device.NewLogger(wgLogLevel(), "[netbird] "),
	)

	t.configurer = configurer.NewUSPConfigurerNoUAPI(t.device, t.name, t.bind.ActivityRecorder())
	err = t.configurer.ConfigureInterface(t.key, t.port)
	if err != nil {
		if cErr := tunIface.Close(); cErr != nil {
			log.Debugf("failed to close tun device: %v", cErr)
		}
		return nil, fmt.Errorf("error configuring interface: %s", err)
	}

	log.Debugf("device has been created: %s", t.name)
	return t.configurer, nil
}

func (t *TunNetstackDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
	if t.device == nil {
		return nil, fmt.Errorf("device is not ready yet")
	}

	err := t.device.Up()
	if err != nil {
		return nil, err
	}

	udpMux, err := t.bind.GetICEMux()
	if err != nil && !errors.Is(err, bind.ErrUDPMUXNotSupported) {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Validate the private key with wgtypes.ParseKey before constructing the device and fail fast with a clear message
  2. Ensure the wg port passed to NewNetstackDevice is within 1-65535 and not already bound by another instance
  3. Enable debug logging to capture the exact ParseKey/IpcSet error text under 'error configuring interface:'
  4. If agent state is corrupted, re-register to generate a fresh key

Example fix

// before
dev := device.NewNetstackDevice(name, addr, port, key, mtu, bind, listenAddr)
cfg, err := dev.Create()

// after
if _, kerr := wgtypes.ParseKey(key); kerr != nil {
    return fmt.Errorf("invalid private key: %w", kerr)
}
dev := device.NewNetstackDevice(name, addr, port, key, mtu, bind, listenAddr)
cfg, err := dev.Create()
Defensive patterns

Strategy: validation

Validate before calling

if _, err := wgtypes.ParseKey(privateKey); err != nil {
    return fmt.Errorf("invalid WireGuard private key: %w", err)
}
if port < 1 || port > 65535 {
    return fmt.Errorf("invalid listen port %d", port)
}

Try / catch

cfg, err := dev.Create()
if err != nil {
    if strings.HasPrefix(err.Error(), "error configuring interface") {
        // key or IpcSet problem: inspect wrapped cause in logs, do not blind-retry
    }
    return err
}

Prevention

When it happens

Trigger: wgtypes.ParseKey rejecting t.key (not a 32-byte base64 key), or device.IpcSet rejecting the listen_port/fwmark value, or running against a device closed concurrently.

Common situations: Corrupted or regenerated WireGuard key in agent state, an out-of-range port passed to NewNetstackDevice, calling create() twice or Close() racing Create() in embedded (client/embed) usage.

Related errors


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