{"record":{"id":"6e17384c5f918309","repo":"slackhq/nebula","slug":"newtun-not-supported-in-ios","errorCode":null,"errorMessage":"newTun not supported in iOS","messagePattern":"newTun not supported in iOS","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_ios.go","lineNumber":34,"sourceCode":"\n\t\"github.com/gaissmai/bart\"\n\t\"github.com/slackhq/nebula/config\"\n\t\"github.com/slackhq/nebula/overlay/tio\"\n\t\"github.com/slackhq/nebula/routing\"\n\t\"github.com/slackhq/nebula/util\"\n\t\"golang.org/x/sys/unix\"\n)\n\ntype tun struct {\n\tio.ReadWriteCloser\n\tvpnNetworks []netip.Prefix\n\tRoutes      atomic.Pointer[[]Route]\n\trouteTree   atomic.Pointer[bart.Table[routing.Gateways]]\n\tl           *slog.Logger\n}\n\nfunc newTun(_ *config.C, _ *slog.Logger, _ []netip.Prefix, _ bool) (*tun, error) {\n\treturn nil, fmt.Errorf(\"newTun not supported in iOS\")\n}\n\nfunc newTunFromFd(c *config.C, l *slog.Logger, deviceFd int, vpnNetworks []netip.Prefix) (*tun, error) {\n\tif err := unix.SetNonblock(deviceFd, true); err != nil {\n\t\t// We own the fd from the moment it is handed to us, same as the reload error path below\n\t\t_ = unix.Close(deviceFd)\n\t\treturn nil, fmt.Errorf(\"failed to set the tun fd to non-blocking mode: %w\", err)\n\t}\n\n\tfile := os.NewFile(uintptr(deviceFd), \"/dev/tun\")\n\tt := &tun{\n\t\tvpnNetworks:     vpnNetworks,\n\t\tReadWriteCloser: &tunReadCloser{f: file},\n\t\tl:               l,\n\t}\n\n\terr := t.reload(c, true)\n\tif err != nil {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_ios.go#L16-L52","documentation":"newTun (overlay/tun_ios.go:34) is a stub on iOS: creating a TUN device directly is not supported because iOS requires the TUN file descriptor to be provided by the NetworkExtension framework. Calling newTun always returns this error unconditionally.","triggerScenarios":"Starting nebula on an iOS build via the default newTun entry point instead of newTunFromFd with an fd obtained from Packet Flow / NEPacketTunnelProvider.","commonSituations":"Embedding nebula in an iOS app but wiring the NetworkExtension incorrectly; using the standard Linux/BSD startup path on iOS; forgetting that iOS builds must supply the device fd from NEPacketTunnelProvider.","solutions":["Obtain the TUN file descriptor from your NEPacketTunnelProvider and call newTunFromFd(c, l, deviceFd, vpnNetworks) instead of newTun.","Ensure the iOS build tag is active so the correct overlay implementation is compiled in.","If you expected TUN creation to work, confirm you are not accidentally building/running the iOS variant on another platform setup."],"exampleFix":"// before\nt, err := newTun(c, l, vpnNetworks, false)\n// after\nfd := packetFlow.FileDescriptor() // from NEPacketTunnelProvider\nt, err := newTunFromFd(c, l, fd, vpnNetworks)","handlingStrategy":"fallback","validationCode":"// iOS: only call newTunFromFd; detect the unsupported path first\nif runtime.GOOS == \"ios\" {\n\t// must supply fd from NEPacketTunnelProvider\n\tfd := packetFlow.FileDescriptor()\n\tt, err = newTunFromFd(c, l, fd, vpnNetworks)\n}","typeGuard":"func tunCreationSupported(goos string) bool {\n\treturn goos != \"ios\"\n}","tryCatchPattern":"t, err := newTun(c, l, vpnNetworks, false)\nif err != nil && strings.Contains(err.Error(), \"not supported in iOS\") {\n\t// switch to newTunFromFd with NetworkExtension-provided fd\n}","preventionTips":["On iOS, always source the TUN fd from NEPacketTunnelProvider and use newTunFromFd.","Gate startup code paths by build tags/GOOS so the stub newTun is never reached on iOS.","Document in the extension integration that direct TUN creation is unsupported."],"tags":["ios","tun","unsupported-platform","network-extension"],"backgroundTag":"unsupported-platform-tun","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}