slackhq/nebula · error
FwpmSubLayerAdd0: 0x%x
Error message
FwpmSubLayerAdd0: 0x%x
What it means
registerSublayer calls FwpmSubLayerAdd0 to add the dynamic, session-scoped sublayer (weight 0xFFFF) to the open engine. This error is thrown when the Win32 call returns non-zero, meaning the sublayer object could not be added to the BFE store. Because the sublayer anchors all subsequent filters, newSession aborts here.
Source
Thrown at wfp/wfp_windows.go:287
key, err := windows.GenerateGUID()
if err != nil {
return windows.GUID{}, fmt.Errorf("GenerateGUID for sublayer: %w", err)
}
name, _ := windows.UTF16PtrFromString("Nebula WDF bypass sublayer")
desc, _ := windows.UTF16PtrFromString("Permit filters bypassing Windows Defender Firewall")
sl := fwpmSublayer0{
subLayerKey: key,
displayData: fwpmDisplayData0{name: name, description: desc},
weight: 0xFFFF,
}
r1, _, _ := procFwpmSubLayerAdd0.Call(
engine,
uintptr(unsafe.Pointer(&sl)),
0, // sd == NULL
)
if r1 != 0 {
return windows.GUID{}, fmt.Errorf("FwpmSubLayerAdd0: 0x%x", r1)
}
return key, nil
}
func addInterfaceFilter(engine uintptr, sublayerKey, layer windows.GUID, luid uint64) error {
name, _ := windows.UTF16PtrFromString("Nebula allow interface inbound")
desc, _ := windows.UTF16PtrFromString("Permits inbound traffic on a nebula interface")
// luid must remain addressable through the syscall -- FWP_UINT64 is stored
// by pointer in the FWP_VALUE0 union.
cond := fwpmFilterCondition0{
fieldKey: fwpmConditionIPLocalInterface,
matchType: fwpMatchEqual,
conditionValue: fwpValue0{
type_: fwpUint64,
value: uintptr(unsafe.Pointer(&luid)),
},
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Retry newSession — transaction conflicts with other WFP clients are typically transient
- Run elevated and confirm the engine was opened in read/write mode
- Check the hex code in the message (e.g. 0x80320009 = FWP_E_TXN_IN_PROGRESS) for the precise cause
- Temporarily disable conflicting third-party WFP agents to test for interference
- Ensure BFE service is healthy: netsh wfp show state
Defensive patterns
Strategy: retry
Validate before calling
func wfpHealthy() bool {
return exec.Command("netsh", "wfp", "show", "state", "file=-").Run() == nil
} Try / catch
s, err := w.PermitUDPPort(port)
if err != nil && strings.Contains(err.Error(), "FwpmSubLayerAdd0") {
// likely transient transaction conflict — retry after delay
time.Sleep(250 * time.Millisecond)
s, err = w.PermitUDPPort(port)
} Prevention
- Retry newSession on sublayer-add failures; conflicts are usually transient
- Avoid running alongside multiple WFP-configuring agents in tests
- Keep the Session usage single-owner: never share the engine handle across goroutines
- Check the hex code: FWP_E_TXN_* codes indicate transaction conflicts
When it happens
Trigger: newSession → registerSublayer where FwpmSubLayerAdd0 fails with codes like FWP_E_ACCESS_DENIED (engine handle lacks write access), FWP_E_TXN_IN_PROGRESS / FWP_E_TXN_ABORTED (transaction conflict), or FWP_E_ALREADY_EXISTS (GUID collision, effectively impossible).
Common situations: Another WFP-managing agent (VPN client, EDR, Windows Firewall itself) holding the BFE transaction, running with a read-only engine handle, or a third-party product rejecting competing sublayer registrations.
Related errors
- FwpmEngineOpen0: 0x%x
- add v4 filter: %w
- add v6 filter: %w
- FwpmFilterAdd0: 0x%x
- GenerateGUID for sublayer: %w
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/47dd0694c195d313.
Report an issue: GitHub.