cloudflare/cloudflared · error
error deleting %s: %v
Error message
error deleting %s: %v
What it means
This error is returned by ServiceTemplate.Remove when os.Remove fails to delete the resolved service file (the launchd plist). It wraps the underlying removal error with the file path. Most commonly the plist does not exist (ENOENT) because the service was never installed or was already removed; it can also be a permission failure since removing from /Library/LaunchDaemons requires root.
Source
Thrown at cmd/cloudflared/service_template.go:78
if err != nil {
return fmt.Errorf("error creating %s: %v", plistFolder, err)
}
err = os.WriteFile(resolvedPath, buffer.Bytes(), fileMode)
if err != nil {
return fmt.Errorf("error writing %s: %v", resolvedPath, err)
}
return nil
}
func (st *ServiceTemplate) Remove() error {
resolvedPath, err := st.ResolvePath()
if err != nil {
return err
}
err = os.Remove(resolvedPath)
if err != nil {
return fmt.Errorf("error deleting %s: %v", resolvedPath, err)
}
return nil
}
func serviceAlreadyExistsWarn(service string) string {
return fmt.Sprintf("cloudflared service is already installed at %s; if you are running a cloudflared tunnel, you "+
"can point it to multiple origins, avoiding the need to run more than one cloudflared service in the "+
"same machine; otherwise if you are really sure, you can do `cloudflared service uninstall` to clean "+
"up the existing service and then try again this command",
service,
)
}
func runCommand(command string, args ...string) error {
cmd := exec.Command(command, args...)
stderr, err := cmd.StderrPipe()
if err != nil {
return fmt.Errorf("error getting stderr pipe: %v", err)View on GitHub (pinned to 2253eeeb25)
Solutions
- Run the uninstall with sudo: sudo cloudflared service uninstall
- If the plist doesn't exist, the service is already removed — check with launchctl list | grep cloudflared and treat as success
- Manually remove a stale file: sudo rm /Library/LaunchDaemons/com.cloudflare.cloudflared.plist (after sudo launchctl bootout/unload of the service)
- Check ownership/flags on the file (ls -laO) and clear immutable flags if present
Example fix
// before
err = os.Remove(resolvedPath)
if err != nil {
return fmt.Errorf("error deleting %s: %v", resolvedPath, err)
}
// after (caller guards against not-installed)
if _, statErr := os.Stat(resolvedPath); os.IsNotExist(statErr) {
return nil // already uninstalled
}
err = os.Remove(resolvedPath)
if err != nil {
return fmt.Errorf("error deleting %s: %v", resolvedPath, err)
} Defensive patterns
Strategy: validation
Validate before calling
resolvedPath, err := st.ResolvePath()
if err != nil { return err }
if _, err := os.Stat(resolvedPath); os.IsNotExist(err) {
return nil // nothing to remove; already uninstalled
}
if err := unix.Access(filepath.Dir(resolvedPath), unix.W_OK); err != nil {
return errors.New("insufficient permission to remove service file; run with sudo")
} Type guard
func serviceFileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
} Try / catch
if err := st.Remove(); err != nil {
if strings.Contains(err.Error(), "no such file or directory") {
return nil // idempotent uninstall: already gone
}
if strings.Contains(err.Error(), "permission denied") {
// advise: sudo cloudflared service uninstall
}
return err
} Prevention
- Stat the plist before removing to make uninstall idempotent
- Run uninstall with sudo on macOS
- Unload/bootout the service from launchctl before deleting the plist
- Treat ENOENT on uninstall as success in scripts
When it happens
Trigger: Calling Remove() (via uninstallLaunchd) when the plist file at resolvedPath does not exist (service not installed / already uninstalled), or when the process lacks permission to delete the file (not run as root, file owned by another user, or sticky/immutable attributes).
Common situations: Running 'cloudflared service uninstall' twice, or uninstalling when the service was never installed; uninstalling without sudo so launchd-owned files can't be deleted; stale plist left behind by an old install under a different user.
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 creating %s: %v
- error writing %s: %v
- error determining executable path: %w
- error generating %s template: %v
- error generating %s: %v
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/c9c893cdc104bf26.
Report an issue: GitHub.