{"record":{"id":"4442829154dec561","repo":"tailscale/tailscale","slug":"cannot-find-q-in-neither-q-nor-path-w","errorCode":null,"errorMessage":"cannot find %q in neither %q nor $PATH: %w","messagePattern":"cannot find %q in neither %q nor \\$PATH: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientupdate/clientupdate.go","lineNumber":1280,"sourceCode":"var binaryPaths = func() (tailscale, tailscaled string, err error) {\n\t// This can be either tailscale or tailscaled.\n\tthis, err := os.Executable()\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\totherName := \"tailscaled\"\n\tif filepath.Base(this) == \"tailscaled\" {\n\t\totherName = \"tailscale\"\n\t}\n\t// Try to find the other binary in the same directory.\n\tother := filepath.Join(filepath.Dir(this), otherName)\n\t_, err = os.Stat(other)\n\tif os.IsNotExist(err) {\n\t\t// If it's not in the same directory, try to find it in $PATH.\n\t\tother, err = exec.LookPath(otherName)\n\t}\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"cannot find %q in neither %q nor $PATH: %w\", otherName, filepath.Dir(this), err)\n\t}\n\tif otherName == \"tailscaled\" {\n\t\treturn this, other, nil\n\t} else {\n\t\treturn other, this, nil\n\t}\n}\n\nfunc haveExecutable(name string) bool {\n\tpath, err := exec.LookPath(name)\n\treturn err == nil && path != \"\"\n}\n\nfunc requestedTailscaleVersion(ver, track string) (string, error) {\n\tif ver != \"\" {\n\t\treturn ver, nil\n\t}\n\treturn LatestTailscaleVersion(track)","sourceCodeStart":1262,"sourceCodeEnd":1298,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/clientupdate/clientupdate.go#L1262-L1298","documentation":"The binaryPaths helper (used by unpackLinuxTarball and friends) resolves the current executable via os.Executable, derives the companion name (tailscale <-> tailscaled), looks for it next to the current binary, and falls back to exec.LookPath. This error means neither the same directory nor $PATH yielded the companion binary, so the updater cannot know where to install both halves of the update.","triggerScenarios":"Only the tailscale CLI was copied somewhere without tailscaled (manual tarball extraction), or tailscaled lives in a directory absent from the invoking user's PATH (e.g. /usr/sbin stripped by sudo's secure_path or a minimal container PATH).","commonSituations":"Running a standalone tailscale binary from ~/bin or /tmp while tailscaled runs from /usr/sbin; containers with a minimal PATH where systemd isn't running tailscaled locally; invoking via sudo with a restricted secure_path.","solutions":["Install both binaries into the same directory: place tailscale and tailscaled side by side (as the official tarball layout does)","Or ensure the companion's directory is on PATH: sudo env \"PATH=$PATH\" tailscale update, or extend secure_path in /etc/sudoers","Symlink the missing companion into the current binary's directory: ln -s /usr/sbin/tailscaled \"$(dirname \"$(command -v tailscale)\")\"/tailscaled","On systems where tailscaled genuinely runs elsewhere (container setups), update through that system's native package manager instead"],"exampleFix":"# before: tailscale in ~/bin, tailscaled in /usr/sbin not on PATH\n$ tailscale update\ncannot find \"tailscaled\" in neither \"/home/user/bin\" nor $PATH: exec: \"tailscaled\": executable file not found in $PATH\n\n# after: keep both binaries together\n$ sudo cp tailscale tailscaled /usr/local/bin/ && hash -r\n$ sudo /usr/local/bin/tailscale update","handlingStrategy":"validation","validationCode":"// Ensure both binaries resolve before starting an update\nfunc bothBinariesResolvable() error {\n\tself, err := os.Executable()\n\tif err != nil { return err }\n\tother := \"tailscaled\"\n\tif filepath.Base(self) == \"tailscaled\" { other = \"tailscale\" }\n\tif _, err := os.Stat(filepath.Join(filepath.Dir(self), other)); err == nil { return nil }\n\tif _, err := exec.LookPath(other); err != nil {\n\t\treturn fmt.Errorf(\"companion %s not next to %s nor on PATH\", other, self)\n\t}\n\treturn nil\n}","typeGuard":"func isCompanionBinaryMissing(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"in neither\") && strings.Contains(err.Error(), \"nor $PATH\")\n}","tryCatchPattern":"if err := up.Update(ctx); err != nil {\n\tif isCompanionBinaryMissing(err) {\n\t\t// install/symlink the companion binary, then retry the update once\n\t\tlog.Printf(\"place tailscale and tailscaled in the same directory or extend PATH\")\n\t}\n\treturn err\n}","preventionTips":["Install tailscale and tailscaled side by side from the official tarball layout","When invoking via sudo, remember secure_path may exclude /usr/sbin — use sudo env PATH=$PATH:... or full paths","In containers, set PATH to include the directory holding both binaries or avoid the in-place updater"],"tags":["filesystem","path","binaries","environment"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}