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
- If the interface is kernel-mode, provide a native firewall or set EnvDisableUserspaceRouting so the switch takes the disable branch
- Ensure GetWGDevice() is populated before EnableRouting (userspace device fully constructed)
- Fix the underlying forwarder.New failure (valid address/MTU) when the device exists but construction fails
- 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
- Set NB env flags deliberately; verify bool spelling (strconv.ParseBool values) since parse errors only warn and fall through to defaults
- Probe GetWGDevice before enabling routing in mixed-mode deployments
- Log which determineRouting branch fired so mode selection is auditable
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
- block wg v4 net: %w
- block wg v6 net: %w
- create forwarder: %w
- block invalid routed: %w
- delete block rule: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/470b24c6249981c6.
Report an issue: GitHub.