netbirdio/netbird · error
create forwarder: %w
Error message
create forwarder: %w
What it means
Returned by initForwarder (client/firewall/uspfilter/filter.go:485) when forwarder.New fails while building the gVisor netstack forwarder. By then GetWGDevice() was non-nil; failure comes from inside the forwarder package - stack options, CreateNIC ('create NIC: %v'), AddProtocolAddress, or listener setup. On failure routingEnabled is set false, so userspace routing (exit nodes, network routes) is disabled for the session even though the manager survives.
Source
Thrown at client/firewall/uspfilter/filter.go:485
}
// initForwarder initializes the forwarder, it disables routing on errors
func (m *Manager) initForwarder() error {
if m.forwarder.Load() != nil {
return nil
}
// Only supported in userspace mode as we need to inject packets back into wireguard directly
intf := m.wgIface.GetWGDevice()
if intf == nil {
m.routingEnabled.Store(false)
return errors.New("forwarding not supported")
}
forwarder, err := forwarder.New(m.wgIface, m.logger, m.flowLogger, m.netstack, m.mtu)
if err != nil {
m.routingEnabled.Store(false)
return fmt.Errorf("create forwarder: %w", err)
}
m.forwarder.Store(forwarder)
// Re-load after store: a concurrent SetPacketCapture may have seen forwarder as nil and only updated pendingCapture.
if pc := m.pendingCapture.Load(); pc != nil {
forwarder.SetCapture(*pc)
}
log.Debug("forwarder initialized")
return nil
}
func (m *Manager) Init(*statemanager.Manager) error {
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Ensure the interface is up with valid v4 (and optional v6) addresses and a sane MTU before EnableRouting
- Retry EnableRouting once after bring-up completes; initForwarder is guarded to run only when the forwarder is nil
- Check logs for the wrapped inner error (create NIC / add protocol address) to pinpoint the failing setup step
- If userspace routing cannot be supported in this environment, run with EnvDisableUserspaceRouting so routing falls through without the forwarder
Example fix
// before
forwarder, err := forwarder.New(m.wgIface, m.logger, m.flowLogger, m.netstack, m.mtu)
if err != nil {
m.routingEnabled.Store(false)
return fmt.Errorf("create forwarder: %w", err)
}
// after
if !m.wgIface.Address().IP.IsValid() || m.mtu == 0 {
m.routingEnabled.Store(false)
return fmt.Errorf("create forwarder: iface address or MTU not ready")
}
forwarder, err := forwarder.New(m.wgIface, m.logger, m.flowLogger, m.netstack, m.mtu)
if err != nil {
m.routingEnabled.Store(false)
return fmt.Errorf("create forwarder: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
if !wgIface.Address().IP.IsValid() || mtu < 576 {
return fmt.Errorf("forwarder prerequisites unmet (addr=%s mtu=%d)", wgIface.Address().IP, mtu)
}
_ = fw.EnableRouting() Type guard
func forwarderPrereqsMet(i common.IFaceMapper, mtu int) bool {
return i.GetWGDevice() != nil && i.Address().IP.IsValid() && mtu >= 576
} Try / catch
if err := fw.EnableRouting(); err != nil {
if strings.Contains(err.Error(), "create forwarder") || strings.Contains(err.Error(), "determine routing") {
// routing degraded, overlay still works; retry after bring-up
scheduleRoutingRetry()
return nil
}
return err
} Prevention
- Bring the interface fully up (address, MTU) before EnableRouting
- initForwarder disables routing on error - re-run EnableRouting once state settles
- Check for the wrapped create NIC / protocol-address messages to find the real prerequisite that failed
When it happens
Trigger: EnableRouting in userspace mode with an interface whose address is unset/invalid (forwarder.New's protocol-address setup fails); MTU of 0 or absurd values passed through; netstack mode where the device endpoint cannot attach; gVisor stack resource exhaustion (memory/nicoleg) on constrained hosts.
Common situations: Enabling routing before the interface is fully configured; embedded/wasm builds where netstack initialization differs; very low-memory containers failing gVisor allocation; MTU misconfiguration via flags or management.
Related errors
- create NIC: %v
- failed to add protocol address: %s
- block wg v4 net: %w
- block wg v6 net: %w
- determine routing: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/e0cbcc126fb50576.
Report an issue: GitHub.