{"record":{"id":"edacbd946c4375ec","repo":"slackhq/nebula","slug":"must-be-using-user-device","errorCode":null,"errorMessage":"must be using user device","messagePattern":"must be using user device","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/service.go","lineNumber":50,"sourceCode":"const nicID = 1\n\ntype Service struct {\n\teg      *errgroup.Group\n\tcontrol *nebula.Control\n\tipstack *stack.Stack\n\n\tmu struct {\n\t\tsync.Mutex\n\n\t\tlisteners map[uint16]*tcpListener\n\t}\n}\n\nfunc New(control *nebula.Control) (_ *Service, reterr error) {\n\t// Check this before Start so a failure doesn't leave a running nebula\n\tdevice, ok := control.Device().(*overlay.UserDevice)\n\tif !ok {\n\t\treturn nil, errors.New(\"must be using user device\")\n\t}\n\n\terr := control.Start()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Anything that fails after a successful Start must tear nebula back down\n\tdefer func() {\n\t\tif reterr != nil {\n\t\t\tcontrol.Stop()\n\t\t}\n\t}()\n\n\tctx := control.Context()\n\teg, ctx := errgroup.WithContext(ctx)\n\ts := Service{\n\t\teg:      eg,","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/service/service.go#L32-L68","documentation":"service.New wraps a nebula Control into the service (device-tunnel) API. It requires the control's device be an *overlay.UserDevice (tun backed by a user-space device handle); any other device type fails with this error before Start is called. The service layer needs the user device to expose file-descriptor based tunneling to the OS.","triggerScenarios":"Calling service.New(control) (from doService, run, or newSimpleService) when control.Device() type-asserts to anything other than *overlay.UserDevice — e.g. the node was started with a regular kernel tun device.","commonSituations":"Running nebula in an environment without the user-device tun option enabled; config using a normal tun interface where service mode expects `-usb`/user device support; embedding the service API against a control built with default tun settings.","solutions":["Start nebula with the user device enabled so control.Device() returns *overlay.UserDevice (service mode requires it).","Check the config/CLI flags that select device type and switch from kernel tun to user device.","If you don't need service/device-tunnel functionality, use the plain nebula Control API instead of service.New."],"exampleFix":"// before (kernel tun)\ncontrol, _ := nebula.Main(config, false, \"\", nil, nil)\ns, err := service.New(control) // panics into error: must be using user device\n// after: launch with user device support, e.g.\n// nebula -service -config config.yaml  (which configures overlay.UserDevice)","handlingStrategy":"type-guard","validationCode":"if _, ok := control.Device().(*overlay.UserDevice); !ok {\n    return errors.New(\"service.New requires a user device; enable user-space tun\")\n}","typeGuard":"func isUserDevice(control *nebula.Control) bool {\n    _, ok := control.Device().(*overlay.UserDevice)\n    return ok\n}","tryCatchPattern":"svc, err := service.New(control)\nif err != nil {\n    if err.Error() == \"must be using user device\" {\n        return fmt.Errorf(\"service mode requires the user device; check your device/tun configuration\")\n    }\n    return err\n}","preventionTips":["Assert the device type before calling service.New to fail with a clearer message","Enable user-device (service) mode in config/CLI when using the service API","Document that plain kernel-tun setups are incompatible with service.New"],"tags":["service","device","nebula","tun"],"backgroundTag":"unsupported-device-type","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"}