netbirdio/netbird · error

block invalid routed: %w

Error message

block invalid routed: %w

What it means

Returned by Manager.EnableRouting (client/firewall/uspfilter/filter.go:1772) wrapping blockInvalidRouted, which installs the default-drop protection against routed traffic entering the overlay. It composes errors 752/753: invalid v4 overlay prefix, or the v6 leg failing after v4 succeeded. Crucially EnableRouting persists the partial rules slice into m.blockRules before returning the error, so the protection that did install is tracked and DisableRouting can remove it.

Source

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

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 {
	m.mutex.Lock()
	defer m.mutex.Unlock()

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

	m.routingEnabled.Store(false)
	m.nativeRouter.Store(false)

	var merr *multierror.Error

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Ensure the interface address (v4 required, v6 optional) is configured and valid before EnableRouting
  2. Retry EnableRouting after bring-up completes; it is mutex-guarded and re-derives rules
  3. Always pair a failed EnableRouting with DisableRouting (or manager Reset) so the persisted partial blockRules are cleaned
  4. Fix the underlying v4/v6 prefix validation issue per errors 752/753

Example fix

// before
if err != nil {
    return fmt.Errorf("block invalid routed: %w", err)
}
// after - keep partial rules tracked, report which family failed
if err != nil {
    _ = m.DisableRouting()
    return fmt.Errorf("block invalid routed (installed %d of 2 rules): %w", len(rules), err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !iface.Address().Network.IsValid() {
    return fmt.Errorf("routing prerequisites unmet: overlay prefix missing")
}
_ = fw.EnableRouting()

Try / catch

if err := fw.EnableRouting(); err != nil {
    if strings.Contains(err.Error(), "block invalid routed") {
        // partial rules were persisted; undo to avoid orphaned drop rules
        if derr := fw.DisableRouting(); derr != nil {
            log.Warnf("cleanup after failed enable: %v", derr)
        }
        return fmt.Errorf("routing enable failed, protection rolled back: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: EnableRouting with an unset interface address (invalid wgPrefix); v6 leg failing with a malformed IPv6 prefix; addRouteFiltering rejecting source networks from the current network map.

Common situations: Routing enabled during engine bring-up races before address assignment; management pushing malformed IPv6 overlay config; partially initialized manager reused after Reset.

Related errors


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