cloudflare/cloudflared · error

error determining executable path: %v

Error message

error determining executable path: %v

What it means

During `cloudflared service install` on Linux, installLinuxService calls os.Executable() to embed the current binary's path into the generated systemd/SysV unit file. If the kernel or runtime cannot resolve the executable path, the install aborts with this error carrying the OS reason (%v).

Source

Thrown at cmd/cloudflared/linux_service.go:259

	Content: `# Configuration for the cloudflared OpenRC service.

# User the cloudflared daemon runs as. Defaults to root.
#cloudflared_user="cloudflared"
`,
}

var noUpdateServiceFlag = &cli.BoolFlag{
	Name:  "no-update-service",
	Usage: "Disable auto-update of the cloudflared linux service, which restarts the server to upgrade for new versions.",
	Value: false,
}

func installLinuxService(c *cli.Context) error {
	log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)

	etPath, err := os.Executable()
	if err != nil {
		return fmt.Errorf("error determining executable path: %v", err)
	}
	templateArgs := ServiceTemplateArgs{
		Path: etPath,
	}

	var extraArgs []string
	if c.NArg() == 0 {
		// If passed no arguments e.g., "$ cloudflared service install",
		// install the service using the detected config file (or error-out if
		// no config exists).
		if extraArgs, err = buildArgsForConfig(c, log); err != nil {
			return err
		}
	} else {
		// If passed one argument e.g., "$ cloudflared service install <token>"
		// write the token to the config directory and install the service
		// using --token-file pointing to that file. This is the quick setup
		// the tunnel UI suggests.

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check the binary still exists at the path you invoked: `which cloudflared` and `ls -l $(which cloudflared)`; reinstall if deleted.
  2. Ensure /proc is mounted (mount -t proc proc /proc) when inside a container or chroot.
  3. Copy the binary to a stable location (e.g. /usr/local/bin/cloudflared) and run service install from there, not from /tmp.
  4. Retry after restoring the binary — os.Executable() reads /proc/self/exe, so a live valid binary resolves the path.

Example fix

// before: binary removed from tmp before install
/tmp/cloudflared service install
// after: stable install location
sudo cp /tmp/cloudflared /usr/local/bin/cloudflared && sudo /usr/local/bin/cloudflared service install
Defensive patterns

Strategy: validation

Validate before calling

// preflight: binary exists and /proc readable (Linux)
func canResolveExecutable() error {
	if _, err := os.Stat("/proc/self/exe"); err != nil {
		return fmt.Errorf("/proc/self/exe unavailable: %w", err)
	}
	return nil
}

Type guard

func executableResolvable() bool { _, err := os.Stat("/proc/self/exe"); return err == nil }

Try / catch

if _, err := os.Executable(); err != nil {
	return fmt.Errorf("cannot install service: executable path unresolved (%v); ensure the binary still exists and /proc is mounted", err)
}

Prevention

When it happens

Trigger: os.Executable() fails — typically because the binary was deleted or replaced after start (Linux returns ENOENT from /proc/self/exe), the binary was built/linked in an unusual way, or /proc is not mounted (containers without procfs).

Common situations: Installing the service from a binary in a temp directory that was removed; running `cloudflared service install` inside a chroot/container with an incomplete /proc; deleting and rebuilding the binary while the CLI process was starting up.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/c4bf893c4683f634. Report an issue: GitHub.