{"record":{"id":"ba323dfbb480437d","repo":"netbirdio/netbird","slug":"interface-has-not-been-initialized-yet","errorCode":null,"errorMessage":"interface has not been initialized yet","messagePattern":"interface has not been initialized yet","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/iface/device/device_windows.go","lineNumber":181,"sourceCode":"\treturn t.mtu\n}\n\nfunc (t *TunDevice) DeviceName() string {\n\treturn t.name\n}\n\nfunc (t *TunDevice) FilteredDevice() *FilteredDevice {\n\treturn t.filteredDevice\n}\n\n// Device returns the wireguard device\nfunc (t *TunDevice) Device() *device.Device {\n\treturn t.device\n}\n\nfunc (t *TunDevice) GetInterfaceGUIDString() (string, error) {\n\tif t.nativeTunDevice == nil {\n\t\treturn \"\", fmt.Errorf(\"interface has not been initialized yet\")\n\t}\n\n\tluid := winipcfg.LUID(t.nativeTunDevice.LUID())\n\tguid, err := luid.GUID()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn guid.String(), nil\n}\n\n// assignAddr Adds IP address to the tunnel interface and network route based on the range provided\nfunc (t *TunDevice) assignAddr() error {\n\tluid := winipcfg.LUID(t.nativeTunDevice.LUID())\n\n\tv4Prefix := t.address.Prefix()\n\tif t.address.HasIPv6() {\n\t\tv6Prefix := t.address.IPv6Prefix()\n\t\tlog.Debugf(\"adding addresses %s, %s to interface: %s\", v4Prefix, v6Prefix, t.name)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/iface/device/device_windows.go#L163-L199","documentation":"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.","triggerScenarios":"Calling GetInterfaceGUIDString before Create(), or after Create() failed at getGUID/CreateTUNWithRequestedGUID so nativeTunDevice was never assigned.","commonSituations":"Firewall/ACL setup code querying the GUID during early startup; partial-failure handling that continues after a Create() error.","solutions":["Call GetInterfaceGUIDString only after Create() returns successfully","Order engine startup so firewall/rule setup runs post-interface-creation","If it still fires, look earlier in the log for the real Create() failure"],"exampleFix":"// before\nguid, err := t.GetInterfaceGUIDString()\n\n// after\nif _, cerr := t.Create(); cerr != nil {\n    return \"\", cerr\n}\nguid, err := t.GetInterfaceGUIDString()","handlingStrategy":"validation","validationCode":"// the GUID exists only after Create() succeeds\nif _, err := dev.Create(); err != nil {\n    return \"\", err\n}\nguid, err := dev.GetInterfaceGUIDString()","typeGuard":"func guidAvailable(dev *device.TunDevice) bool {\n    return dev != nil && dev.Device() != nil && dev.FilteredDevice() != nil\n}","tryCatchPattern":"guid, err := dev.GetInterfaceGUIDString()\nif err != nil {\n    if strings.Contains(err.Error(), \"interface has not been initialized yet\") {\n        // ordering bug: create the interface before requesting its GUID\n    }\n    return \"\", err\n}","preventionTips":["Sequence firewall/ACL setup after successful interface creation","Never continue past a failed Create()","Cache the GUID after first successful retrieval instead of re-querying early"],"tags":["windows","lifecycle","guid","adapter","state"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}