slackhq/nebula · error

newTunFromFd not supported

Error message

newTunFromFd not supported

What it means

newTunFromFd in overlay/tun_tester.go is a stub: the tester TUN implementation only supports creating a device from config, not from a file descriptor. Calling it always returns 'newTunFromFd not supported'. It exists so the test harness satisfies the Device constructor interface.

Source

Thrown at overlay/tun_tester.go:56

	}
	routeTree, err := makeRouteTree(l, routes, false)
	if err != nil {
		return nil, err
	}

	return &TestTun{
		Device:      c.GetString("tun.dev", ""),
		vpnNetworks: vpnNetworks,
		Routes:      routes,
		routeTree:   routeTree,
		l:           l,
		rxPackets:   make(chan []byte, 10),
		TxPackets:   make(chan []byte, 10),
	}, nil
}

func newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (*TestTun, error) {
	return nil, fmt.Errorf("newTunFromFd not supported")
}

// Send will place a byte array onto the receive queue for nebula to consume.
// These are unencrypted ip layer frames destined for another nebula node.
// packets should exit the udp side, capture them with udpConn.Get.
//
// Send copies the input via the freelist, so the caller is free to mutate
// or reuse it after the call returns.
func (t *TestTun) Send(packet []byte) {
	if t.closed.Load() {
		return
	}

	if t.l.Enabled(context.Background(), slog.LevelDebug) {
		t.l.Debug("Tun receiving injected packet", "dataLen", len(packet))
	}
	buf := acquireTunBuf(len(packet))
	copy(buf, packet)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Don't pass a pre-opened fd when using the tester overlay; remove tun.fd from the config so newTun is used instead.
  2. Use the real OS overlay (linux/bsd) if you need fd-based TUN handoff.
  3. If you need this in tests, implement fd support in TestTun or mock the constructor in your harness.

Example fix

// before
c:
  tun:
    fd: 3
// after
c:
  tun:
    dev: tun0   # let the tester/OS create the device instead of handing in an fd
Defensive patterns

Strategy: fallback

Validate before calling

if fd, ok := c.GetInt("tun.fd"); ok && fd > 0 {
	return errors.New("tester overlay does not support tun.fd; remove it from config")
}

Try / catch

tun, err := overlay.NewTunFromFd(cfg, logger, fd, prefixes)
if err != nil && strings.Contains(err.Error(), "not supported") {
	tun, err = overlay.NewTun(cfg, logger, prefixes, false) // fallback to normal creation
}

Prevention

When it happens

Trigger: Invoking newTunFromFd with a *config.C, logger, fd int and prefixes while running against the TestTun/tester overlay — i.e. code paths that use tun.fd on the test build.

Common situations: Running nebula in test mode with a config that specifies tun.fd or handoff of a pre-opened tunnel fd; custom integration harnesses that assume fd-based TUN injection works under the tester.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/f6f3d9367d68b9f9. Report an issue: GitHub.