tailscale/tailscale · error

cannot find %q in neither %q nor $PATH: %w

Error message

cannot find %q in neither %q nor $PATH: %w

What it means

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.

Source

Thrown at clientupdate/clientupdate.go:1280

var binaryPaths = func() (tailscale, tailscaled string, err error) {
	// This can be either tailscale or tailscaled.
	this, err := os.Executable()
	if err != nil {
		return "", "", err
	}
	otherName := "tailscaled"
	if filepath.Base(this) == "tailscaled" {
		otherName = "tailscale"
	}
	// Try to find the other binary in the same directory.
	other := filepath.Join(filepath.Dir(this), otherName)
	_, err = os.Stat(other)
	if os.IsNotExist(err) {
		// If it's not in the same directory, try to find it in $PATH.
		other, err = exec.LookPath(otherName)
	}
	if err != nil {
		return "", "", fmt.Errorf("cannot find %q in neither %q nor $PATH: %w", otherName, filepath.Dir(this), err)
	}
	if otherName == "tailscaled" {
		return this, other, nil
	} else {
		return other, this, nil
	}
}

func haveExecutable(name string) bool {
	path, err := exec.LookPath(name)
	return err == nil && path != ""
}

func requestedTailscaleVersion(ver, track string) (string, error) {
	if ver != "" {
		return ver, nil
	}
	return LatestTailscaleVersion(track)

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Install both binaries into the same directory: place tailscale and tailscaled side by side (as the official tarball layout does)
  2. Or ensure the companion's directory is on PATH: sudo env "PATH=$PATH" tailscale update, or extend secure_path in /etc/sudoers
  3. Symlink the missing companion into the current binary's directory: ln -s /usr/sbin/tailscaled "$(dirname "$(command -v tailscale)")"/tailscaled
  4. On systems where tailscaled genuinely runs elsewhere (container setups), update through that system's native package manager instead

Example fix

# before: tailscale in ~/bin, tailscaled in /usr/sbin not on PATH
$ tailscale update
cannot find "tailscaled" in neither "/home/user/bin" nor $PATH: exec: "tailscaled": executable file not found in $PATH

# after: keep both binaries together
$ sudo cp tailscale tailscaled /usr/local/bin/ && hash -r
$ sudo /usr/local/bin/tailscale update
Defensive patterns

Strategy: validation

Validate before calling

// Ensure both binaries resolve before starting an update
func bothBinariesResolvable() error {
	self, err := os.Executable()
	if err != nil { return err }
	other := "tailscaled"
	if filepath.Base(self) == "tailscaled" { other = "tailscale" }
	if _, err := os.Stat(filepath.Join(filepath.Dir(self), other)); err == nil { return nil }
	if _, err := exec.LookPath(other); err != nil {
		return fmt.Errorf("companion %s not next to %s nor on PATH", other, self)
	}
	return nil
}

Type guard

func isCompanionBinaryMissing(err error) bool {
	return err != nil && strings.Contains(err.Error(), "in neither") && strings.Contains(err.Error(), "nor $PATH")
}

Try / catch

if err := up.Update(ctx); err != nil {
	if isCompanionBinaryMissing(err) {
		// install/symlink the companion binary, then retry the update once
		log.Printf("place tailscale and tailscaled in the same directory or extend PATH")
	}
	return err
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/4442829154dec561. Report an issue: GitHub.