netbirdio/netbird · error

determine routing: %w

Error message

determine routing: %w

What it means

Returned by Manager.EnableRouting (client/firewall/uspfilter/filter.go:1760) wrapping determineRouting. determineRouting parses EnvDisableUserspaceRouting / EnvForceUserspaceRouter (parse failures only warn) then switches to a routing mode; the only error paths are initForwarder's: 'forwarding not supported' when wgIface.GetWGDevice() is nil, or 'create forwarder: %w'. So this error means the chosen mode demands userspace routing but the device cannot support it, or forwarder construction failed.

Source

Thrown at client/firewall/uspfilter/filter.go:1760

// SetTCPPacketHook sets the outbound TCP packet hook. Pass nil hook to remove.
func (m *Manager) SetTCPPacketHook(ip netip.Addr, dPort uint16, hook func(packet []byte) bool) {
	common.SetHook(&m.tcpHookOut, ip, dPort, hook)
}

// SetLogLevel sets the log level for the firewall manager
func (m *Manager) SetLogLevel(level log.Level) {
	if m.logger != nil {
		m.logger.SetLevel(nblog.Level(level))
	}
}

func (m *Manager) EnableRouting() error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	if err := m.determineRouting(); err != nil {
		return fmt.Errorf("determine routing: %w", err)
	}

	if m.forwarder.Load() == nil {
		return nil
	}

	rules, err := m.blockInvalidRouted(m.wgIface)
	// Persist whatever was installed even on partial failure, so DisableRouting
	// can clean it up later.
	m.blockRules = rules
	if err != nil {
		return fmt.Errorf("block invalid routed: %w", err)
	}

	return nil
}

func (m *Manager) DisableRouting() error {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. If the interface is kernel-mode, provide a native firewall or set EnvDisableUserspaceRouting so the switch takes the disable branch
  2. Ensure GetWGDevice() is populated before EnableRouting (userspace device fully constructed)
  3. Fix the underlying forwarder.New failure (valid address/MTU) when the device exists but construction fails
  4. Check the wrapped message to distinguish 'forwarding not supported' (mode problem) from 'create forwarder' (setup problem)

Example fix

// before
if err := m.determineRouting(); err != nil {
    return fmt.Errorf("determine routing: %w", err)
}
// after
if err := m.determineRouting(); err != nil {
    if errors.Is(err, errForwardingNotSupported) && m.wgIface.GetWGDevice() == nil {
        log.Info("kernel device without userspace routing support; routing disabled")
        return nil
    }
    return fmt.Errorf("determine routing: %w", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Choose routing mode explicitly instead of relying on device probing
if wgIface.GetWGDevice() == nil && nativeFirewall == nil {
    os.Setenv(EnvDisableUserspaceRouting, "true")
}

Type guard

func canRouteUserspace(wg common.IFaceMapper) bool {
    return wg.GetWGDevice() != nil
}

Try / catch

if err := fw.EnableRouting(); err != nil {
    if strings.Contains(err.Error(), "forwarding not supported") {
        log.Info("userspace forwarding unavailable on this device; routing off")
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: EnableRouting in kernel WireGuard mode where GetWGDevice() returns nil (the default branch selects userspace routing when nativeFirewall is nil or netstack is on); forceUserspaceRouter set via env on a kernel-mode interface; netstack mode with forwarder.New failing as in error 754.

Common situations: Miscombined env flags (forcing userspace routing on kernel mode); platforms where nativeFirewall detection fails so default falls into userspace routing; embedded netstack builds.

Related errors


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