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

  1. Retry newSession — transaction conflicts with other WFP clients are typically transient
  2. Run elevated and confirm the engine was opened in read/write mode
  3. Check the hex code in the message (e.g. 0x80320009 = FWP_E_TXN_IN_PROGRESS) for the precise cause
  4. Temporarily disable conflicting third-party WFP agents to test for interference
  5. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/47dd0694c195d313. Report an issue: GitHub.