{"record":{"id":"257df4c5cf8c1e0f","repo":"netbirdio/netbird","slug":"s-w-257df4","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/service_pipe_windows.go","lineNumber":34,"sourceCode":"\n// listenNamedPipe creates the daemon control pipe and reports the path it ended\n// up on. The security descriptor lets any local caller connect, as a Unix socket\n// at 0666 does, and the privileged operations are authorized separately from the\n// caller's token.\n//\n// The protected name comes first so that an unprivileged process cannot take the\n// name before the service does. Creating it requires being an administrator or\n// LocalSystem, so a daemon an ordinary user runs themselves, as in netstack mode,\n// falls back to the plain name; clients try both and check who serves them.\nfunc listenNamedPipe(name string) (net.Listener, string, error) {\n\tvar errs []error\n\tfor _, path := range daemonaddr.PipePaths(name) {\n\t\tlistener, err := winio.ListenPipe(path, &winio.PipeConfig{\n\t\t\tSecurityDescriptor: ipcauth.DefaultPipeSDDL(),\n\t\t})\n\t\tif err != nil {\n\t\t\tlog.Debugf(\"not serving the daemon on %s: %v\", path, err)\n\t\t\terrs = append(errs, fmt.Errorf(\"%s: %w\", path, err))\n\t\t\tcontinue\n\t\t}\n\t\treturn listener, path, nil\n\t}\n\n\treturn nil, \"\", errors.Join(errs...)\n}\n","sourceCodeStart":16,"sourceCodeEnd":42,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/service_pipe_windows.go#L16-L42","documentation":"On Windows, listenNamedPipe tried every candidate pipe path (protected name first, then the plain name) and each winio.ListenPipe call failed; errors.Join merges one error per path. The protected name needs administrator/LocalSystem, and failure of both names means the daemon could not serve on either.","triggerScenarios":"Another netbird daemon already listening on the pipe names (service running while `service run` or the embedded daemon starts); a security descriptor rejected for the caller's token; a malformed pipe name.","commonSituations":"Starting a second daemon while the installed Windows service is active; running the netstack/embedded client concurrently with the service.","solutions":["Ensure a single daemon instance: stop the service first (netbird service stop / Stop-Service netbird)","Run the daemon elevated if the protected pipe name is required","Choose a different --daemon-addr pipe name to avoid the collision","Read each joined error: access denied points to privileges, pipe-busy/file-in-use points to an existing listener"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"for _, p := range daemonaddr.PipePaths(name) {\n\tif c, err := winio.DialPipe(p, &winio.DialPipeTimeout{Timeout: 100 * time.Millisecond}); err == nil {\n\t\t_ = c.Close()\n\t\treturn fmt.Errorf(\"pipe %s already served by another daemon\", p)\n\t}\n}","typeGuard":null,"tryCatchPattern":"listener, path, err := listenNamedPipe(name)\nif err != nil {\n\t// both candidate names failed; the joined errors distinguish privileges from an existing listener\n\tif isAccessDenied(err) {\n\t\treturn retryElevated()\n\t}\n\treturn fallbackToTCPIfAllowed()\n}","preventionTips":["Guarantee one daemon instance per machine before starting another","Stop the installed service before running the daemon in the foreground","Prefer the protected pipe name and run the service as LocalSystem"],"tags":["daemon","named-pipe","windows","concurrency","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}