slackhq/nebula · error
FwpmFilterAdd0: 0x%x
Error message
FwpmFilterAdd0: 0x%x
What it means
addInterfaceFilter installs a PERMIT filter in the ALE layer that matches inbound traffic on a specific interface LUID, letting it bypass Windows Defender Firewall. This error wraps a non-zero return from FwpmFilterAdd0 — the filter object could not be added to the engine. The call comes from the public PermitInterface API.
Source
Thrown at wfp/wfp_windows.go:326
// filterKey left zero: WFP assigns one when the filter is added.
displayData: fwpmDisplayData0{name: name, description: desc},
flags: fwpmFilterFlagClearActionRight,
layerKey: layer,
subLayerKey: sublayerKey,
weight: fwpValue0{type_: fwpUint8, value: uintptr(15)},
numFilterConditions: 1,
filterCondition: &cond,
action: fwpmAction0{actionType: fwpActionPermit},
}
r1, _, _ := procFwpmFilterAdd0.Call(
engine,
uintptr(unsafe.Pointer(&filter)),
0, // sd == NULL
0, // id == NULL
)
if r1 != 0 {
return fmt.Errorf("FwpmFilterAdd0: 0x%x", r1)
}
return nil
}
// addUDPPortFilter installs a PERMIT filter that matches (IP_PROTOCOL == UDP) AND (IP_LOCAL_PORT == port).
// FWP_UINT8 and FWP_UINT16 are <= 32 bits so they live inline in the FWP_VALUE0 union.
func addUDPPortFilter(engine uintptr, sublayerKey, layer windows.GUID, port uint16) error {
name, _ := windows.UTF16PtrFromString("Nebula allow UDP port inbound")
desc, _ := windows.UTF16PtrFromString("Permits inbound UDP to a nebula listener port")
conds := [2]fwpmFilterCondition0{
{
fieldKey: fwpmConditionIPProtocol,
matchType: fwpMatchEqual,
conditionValue: fwpValue0{
type_: fwpUint8,
value: uintptr(ipprotoUDP),
},View on GitHub (pinned to dd8f660c0a)
Solutions
- Decode the hex win32 code for the exact FWP_E_* cause
- Verify the interface LUID is current (Get-NetAdapter / netsh interface show interface) and re-fetch it immediately before calling
- Run the process as Administrator
- Retry — transient transaction conflicts with other WFP agents resolve on re-attempt
- Ensure PermitUDPPort/newSession succeeded and the Session has not been Closed before calling PermitInterface
Example fix
// before
luid := staleLuid // cached from long ago
if err := w.PermitInterface(luid); err != nil { ... }
// after — refresh LUID at call time
adapter, _ := net.InterfaceByName(name)
luid := uint64(adapter.Index)
if err := w.PermitInterface(luid); err != nil {
return fmt.Errorf("permit interface: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func interfaceExists(luid uint64) error {
ifaces, err := net.Interfaces()
if err != nil { return err }
for _, ifc := range ifaces {
if uint64(ifc.Index) == luid { return nil }
}
return fmt.Errorf("interface with LUID %d not found", luid)
}
// call before PermitInterface
if err := interfaceExists(luid); err != nil { return err } Try / catch
if err := w.PermitInterface(luid); err != nil {
var winErr syscall.Errno
if errors.As(err, &winErr) && winErr == 0x80320009 { // FWP_E_TXN_IN_PROGRESS
time.Sleep(200 * time.Millisecond)
return w.PermitInterface(luid)
}
return err
} Prevention
- Re-resolve the interface LUID immediately before calling PermitInterface
- Verify the Session is open (not Closed) before adding interface filters
- Run elevated; FwpmFilterAdd0 requires write access to the engine
- Handle interface hot-unplug: re-permit after adapter changes
When it happens
Trigger: Calling PermitInterface where FwpmFilterAdd0 fails: invalid/unknown interface LUID, filter conditions rejected (FWP_E_INVALID_PARAMETER), access denied on the engine handle, transaction conflict with another WFP client, or the sublayer/session was already closed via Close().
Common situations: Passing an LUID that no longer exists (interface unplugged/renamed between lookup and call), running without admin rights, an EDR/VPN product holding the BFE transaction, or calling after the Session was closed.
Related errors
- add v4 filter: %w
- add v6 filter: %w
- FwpmEngineOpen0: 0x%x
- FwpmSubLayerAdd0: 0x%x
- create TUN device failed: %w
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/c3e78907e920809f.
Report an issue: GitHub.