cloudflare/cloudflared · error
error resolving path for service %q: %w
Error message
error resolving path for service %q: %w
What it means
uninstallSystemd iterates over all known systemd service templates and calls ServiceTemplate.ResolvePath() (homedir.Expand on the template path) to determine whether each service file is installed. If expanding the path fails, cloudflared aborts the whole systemd uninstall with this wrapped error. It exists because the uninstall cannot safely decide which service files to remove without knowing their concrete paths.
Source
Thrown at cmd/cloudflared/linux_service.go:473
err = uninstallSysv(log)
}
removeTokenFile(serviceConfigDir, log)
if err == nil {
log.Info().Msg("Linux service for cloudflared uninstalled successfully")
}
return err
}
func uninstallSystemd(log *zerolog.Logger) error {
// Get only the installed services
installedServices := make(map[string]ServiceTemplate)
for serviceName, serviceTemplate := range systemdAllTemplates {
path, err := serviceTemplate.ResolvePath()
if err != nil {
return fmt.Errorf("error resolving path for service %q: %w", serviceName, err)
}
if _, err := os.Stat(path); err == nil {
installedServices[serviceName] = serviceTemplate
} else {
log.Info().Msgf("Service '%s' not installed, skipping its uninstall", serviceName)
}
}
if _, exists := installedServices[cloudflaredService]; exists {
if err := runCommand("systemctl", "disable", cloudflaredService); err != nil {
log.Err(err).Msgf("systemctl disable %s error", cloudflaredService)
return err
}
if err := runCommand("systemctl", "stop", cloudflaredService); err != nil {
log.Err(err).Msgf("systemctl stop %s error", cloudflaredService)
return err
}
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Run the uninstall with a valid HOME: `sudo HOME=/root cloudflared service uninstall`
- Check `echo $HOME` is set and points to an existing user's directory; fix the environment if empty or bogus
- Ensure the invoking user exists in /etc/passwd (getent passwd $(id -u)) so homedir.Expand can resolve '~'
- As a workaround, remove the unit files manually: `sudo rm /etc/systemd/system/cloudflared.service` (and any *.service cloudflared variants) then `sudo systemctl daemon-reload`
- Read the wrapped (%w) error — it names the exact template path and expansion failure
Example fix
// before: cron-like env without HOME $ cloudflared service uninstall // error: error resolving path for service "cloudflared": error resolving path /etc/systemd/system/cloudflared.service: ... // after $ sudo HOME=/root cloudflared service uninstall
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight env check before running service uninstall
func ensureUninstallEnv() error {
if os.Getenv("HOME") == "" {
return errors.New("HOME is unset; set HOME (e.g. HOME=/root) before running service uninstall")
}
if _, err := exec.LookPath("systemctl"); err != nil {
return errors.New("systemctl not found: not a systemd system")
}
return nil
} Type guard
func homeResolvable() bool {
home := os.Getenv("HOME")
if home == "" {
if u, err := user.Current(); err == nil && u.HomeDir != "" {
return true
}
return false
}
return true
} Prevention
- Ensure HOME is exported when running cloudflared from cron, CI, or containers (sudo -H or explicit HOME=/root)
- Run service management commands as a real user with a passwd entry
- Prefer `sudo -H cloudflared service uninstall` in scripts
- If uninstall keeps failing, remove unit files manually and run systemctl daemon-reload
When it happens
Trigger: During `cloudflared service uninstall` on a Linux host with systemd, when homedir.Expand() fails on one of the systemdAllTemplates paths — practically only when the path contains a '~' that cannot be resolved because HOME/username lookup fails (e.g. empty or invalid HOME env, unknown user).
Common situations: Running the uninstall from an environment with no valid HOME set (cron job, systemd unit, container with stripped env); running as a UID that has no passwd entry so user lookup inside homedir.Expand fails; sandboxed environments where os/user lookups are restricted (CGO disabled + unusual NSS setup).
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
- error resolving OpenRC template path: %w
- error removing %s: %w
- error determining executable path: %v
- could not write token to configuration directory: %w
- error generating OpenRC conf.d template: %w
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/5c34851966dd9968.
Report an issue: GitHub.