FWP_E_INCOMPATIBLE_LAYER (0x80320014) — What Layer? Fix Now
You're trying to shove a filter into a Windows Filtering Platform layer that doesn't support it. It's a dev or config mismatch. I'll show you the three fixes.
If you're seeing FWP_E_INCOMPATIBLE_LAYER (0x80320014), it means your Windows Filtering Platform (WFP) filter or callout driver tried to do something at a layer that doesn't support it. The culprit here is almost always a mismatch between what you're trying to filter and the layer's intended purpose. I've seen this on Windows 10 20H2 through Server 2022, especially with custom firewall apps or VPN drivers.
Here are the three most common causes, ordered by frequency. Fix them in this order and you'll save yourself an hour of head-scratching.
1. Wrong Layer for the Filter Type
This is the classic case. WFP layers are strict about what kind of filters they accept. You can't add a stream filter (like FWPM_LAYER_STREAM_V4) to a datagram layer (like FWPM_LAYER_DATAGRAM_DATA_V4). The error fires because the layer's schema doesn't match the filter's conditions or action type.
Real-world trigger: You're using a third-party firewall app (e.g., Comodo, TinyWall) or a custom VPN client that injects WFP filters. The app's code tries to set a block rule at FWPM_LAYER_ALE_AUTH_CONNECT_V4, but the filter uses stream-layer conditions like FWPM_CONDITION_IP_LOCAL_PORT with a stream-layer action. That's a no-go.
Fix: Identify the exact layer GUID and filter type, then remap it.
# List all layers and their types
netsh wfp show layers
Check the LayerId and compare it with MSDN docs. For example:
- ALE layers (e.g.,
FWPM_LAYER_ALE_AUTH_CONNECT_V4) expectFWP_ACTION_BLOCKorFWP_ACTION_PERMITand conditions like remote IP, not stream data. - Stream layers (e.g.,
FWPM_LAYER_STREAM_V4) expect conditions likeFWPM_CONDITION_STREAM_PACKET_DIRECTION. - Datagram layers (e.g.,
FWPM_LAYER_DATAGRAM_DATA_V4) expectFWPM_CONDITION_IP_LOCAL_PORTbut no stream-specific conditions.
If you're writing the filter programmatically (C++ or PowerShell), make sure your FWPM_FILTER0.layerKey matches the correct layer GUID. Here's a common mismatch I've fixed a dozen times:
// Wrong: stream layer with ALE connect filter
FWPM_FILTER0 filter = {0};
filter.layerKey = FWPM_LAYER_STREAM_V4; // Should be FWPM_LAYER_ALE_AUTH_CONNECT_V4
filter.action.type = FWP_ACTION_BLOCK;
// This will throw 0x80320014
Change the layerKey to the right one, recompile, done.
2. Missing or Mismatched Callout Driver
WFP callout drivers are tied to specific layers. If your filter references a callout (via FWPM_FILTER0.action.calloutKey), but that callout isn't registered at the same layer, you get this error. The layer sees the callout as incompatible.
Real-world trigger: You updated a third-party network driver (like a proxy client or SSL inspection tool) and the new version changed its callout registration. Old filters still point to the old callout GUID, or the callout now lives at a different layer.
Fix: Verify the callout's registered layer.
# List all callouts and their layer bindings
netsh wfp show callouts
Look at the AppliedLayer column. If your filter's layerKey doesn't match, you have two options:
- Update the filter to use a callout that's registered at the correct layer.
- Re-register the callout at the layer you need (requires driver code changes and at least a reload, often a reboot).
If you're the driver developer, check your FwpsCalloutRegister call. The second parameter (layer GUID) must match the layer where you'll add filters. I've seen teams forget to update this after moving from Windows 8.1 to Windows 10's new layers.
Skip uninstalling and reinstalling the driver — it rarely helps if the code's wrong. Instead, use sc query to check the driver's state, then update the callout registration in the source.
3. Filter Flags Not Compatible with Layer
Some layers have restrictions on which filter flags you can set. For example, FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT is only valid on certain ALE layers. If you apply it to a forwarding layer, you'll get 0x80320014.
Real-world trigger: A network monitoring tool that sets FWPM_FILTER_FLAG_INDEXED on an inbound transport layer. That flag is only for ALE layers. The tool's developer didn't check the docs.
Fix: Review your filter flags against the layer's supported flags. Microsoft's documentation has a table for each layer under FWPM_FILTER_FLAG constants. The key ones to watch:
| Flag | Valid Layers |
|---|---|
FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT | ALE layers only (e.g., ALE_AUTH_CONNECT, ALE_AUTH_LISTEN) |
FWPM_FILTER_FLAG_INDEXED | ALE layers only |
FWPM_FILTER_FLAG_BOOTTIME | Boot-time layers only (e.g., FWPM_LAYER_INBOUND_IPPACKET_V4) |
FWPM_FILTER_FLAG_PERSISTENT | All layers, but careful — it can cause boot loops if misused |
To fix, remove the offending flag from your filter. If you're building the filter in PowerShell with the NetFirewall cmdlets, you can't set these flags directly — they're internal. But if you're using the WFP API directly (C/C++), double-check your flags field.
// Remove this line if at a non-ALE layer:
filter.flags = FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT;
// Replace with 0 or FWPM_FILTER_FLAG_NONE
After any of these fixes, restart the Base Filtering Engine service to force a reload:
net stop BFE
net start BFE
Or just reboot. Yes, it's lazy, but it clears stale state. I always do a reboot after fixing callout registrations.
Quick-Reference Summary Table
| Cause | Symptom | Fix |
|---|---|---|
| Wrong layer for filter type | Filter added to stream layer but uses ALE conditions | Change layerKey to match filter action |
| Missing/mismatched callout driver | Callout not registered at filter's layer | Update callout registration or filter's calloutKey |
| Incompatible filter flags | Flags like CLEAR_ACTION_RIGHT set on non-ALE layer | Remove the flag |
That's it. Three causes, three fixes. Start with #1 — it's the most common by a long shot. And for god's sake, test your filters on a VM before pushing to production. I've seen this error take down a corporate VPN because someone pushed a WFP filter to the wrong layer company-wide.
Was this solution helpful?