netbirdio/netbird · error

interface has not been initialized yet

Error message

interface has not been initialized yet

What it means

GetInterfaceGUIDString() converts the adapter LUID to a GUID (winipcfg LUID.GUID()) for callers such as firewall rules or the UI. It refuses with this error while nativeTunDevice is nil, which is the state before Create() reaches tun creation or after an earlier Create() step failed. It is a pure initialization-ordering guard.

Source

Thrown at client/iface/device/device_windows.go:181

	return t.mtu
}

func (t *TunDevice) DeviceName() string {
	return t.name
}

func (t *TunDevice) FilteredDevice() *FilteredDevice {
	return t.filteredDevice
}

// Device returns the wireguard device
func (t *TunDevice) Device() *device.Device {
	return t.device
}

func (t *TunDevice) GetInterfaceGUIDString() (string, error) {
	if t.nativeTunDevice == nil {
		return "", fmt.Errorf("interface has not been initialized yet")
	}

	luid := winipcfg.LUID(t.nativeTunDevice.LUID())
	guid, err := luid.GUID()
	if err != nil {
		return "", err
	}
	return guid.String(), nil
}

// assignAddr Adds IP address to the tunnel interface and network route based on the range provided
func (t *TunDevice) assignAddr() error {
	luid := winipcfg.LUID(t.nativeTunDevice.LUID())

	v4Prefix := t.address.Prefix()
	if t.address.HasIPv6() {
		v6Prefix := t.address.IPv6Prefix()
		log.Debugf("adding addresses %s, %s to interface: %s", v4Prefix, v6Prefix, t.name)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Call GetInterfaceGUIDString only after Create() returns successfully
  2. Order engine startup so firewall/rule setup runs post-interface-creation
  3. If it still fires, look earlier in the log for the real Create() failure

Example fix

// before
guid, err := t.GetInterfaceGUIDString()

// after
if _, cerr := t.Create(); cerr != nil {
    return "", cerr
}
guid, err := t.GetInterfaceGUIDString()
Defensive patterns

Strategy: validation

Validate before calling

// the GUID exists only after Create() succeeds
if _, err := dev.Create(); err != nil {
    return "", err
}
guid, err := dev.GetInterfaceGUIDString()

Type guard

func guidAvailable(dev *device.TunDevice) bool {
    return dev != nil && dev.Device() != nil && dev.FilteredDevice() != nil
}

Try / catch

guid, err := dev.GetInterfaceGUIDString()
if err != nil {
    if strings.Contains(err.Error(), "interface has not been initialized yet") {
        // ordering bug: create the interface before requesting its GUID
    }
    return "", err
}

Prevention

When it happens

Trigger: Calling GetInterfaceGUIDString before Create(), or after Create() failed at getGUID/CreateTUNWithRequestedGUID so nativeTunDevice was never assigned.

Common situations: Firewall/ACL setup code querying the GUID during early startup; partial-failure handling that continues after a Create() error.

Related errors


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