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

  1. Ensure the interface is up with valid v4 (and optional v6) addresses and a sane MTU before EnableRouting
  2. Retry EnableRouting once after bring-up completes; initForwarder is guarded to run only when the forwarder is nil
  3. Check logs for the wrapped inner error (create NIC / add protocol address) to pinpoint the failing setup step
  4. 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

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


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/e0cbcc126fb50576. Report an issue: GitHub.