caddyserver/caddy · warning

download succeeded, but unable to clean up backup binary: %v

Error message

download succeeded, but unable to clean up backup binary: %v

What it means

The upgrade itself fully succeeded (downloaded, verified, executed), but removing the backup file '<exec>.tmp' failed because --keep-backup was not set. Despite the message prefix, the new binary is in place and working; only the leftover backup is the issue. Note the deferred restore does NOT run because err is set, so the .tmp file is intentionally left for manual cleanup.

Source

Thrown at cmd/packagesfuncs.go:205

	}

	l.Info("download successful; displaying new binary details", zap.String("location", thisExecPath))

	// use the new binary to print out version and module info
	fmt.Print("\nModule versions:\n\n")
	if err = listModules(thisExecPath); err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to execute 'caddy list-modules': %v", err)
	}
	fmt.Println("\nVersion:")
	if err = showVersion(thisExecPath); err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to execute 'caddy version': %v", err)
	}
	fmt.Println()

	// clean up the backup file
	if !fl.Bool("keep-backup") {
		if err = removeCaddyBinary(backupExecPath); err != nil {
			return caddy.ExitCodeFailedStartup, fmt.Errorf("download succeeded, but unable to clean up backup binary: %v", err)
		}
	} else {
		l.Info("skipped cleaning up the backup file", zap.String("backup_path", backupExecPath))
	}

	l.Info("upgrade successful; please restart any running Caddy instances", zap.String("executable", thisExecPath))

	return caddy.ExitCodeSuccess, nil
}

func getModules() (standard, nonstandard, unknown []moduleInfo, err error) {
	bi, ok := debug.ReadBuildInfo()
	if !ok {
		err = fmt.Errorf("no build info")
		return standard, nonstandard, unknown, err
	}

	for _, modID := range caddy.Modules() {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Verify the new binary works: caddy version — the upgrade itself succeeded
  2. Delete the leftover backup with appropriate privileges: sudo rm -f /path/to/caddy.tmp
  3. Pass --keep-backup on future upgrades if you want the backup retained deliberately
  4. Fix ownership of the binary directory so future runs can clean up: sudo chown $(id -u) <dir>

Example fix

# before
caddy upgrade
# error: download succeeded, but unable to clean up backup binary: remove /usr/local/bin/caddy.tmp: permission denied

# after
sudo rm -f /usr/local/bin/caddy.tmp
caddy version  # confirm upgrade took effect
Defensive patterns

Strategy: validation

Validate before calling

caddy version                      # confirm upgrade landed
ls -l "$(command -v caddy).tmp" 2>/dev/null && sudo rm -f "$(command -v caddy).tmp"

Prevention

When it happens

Trigger: os.Remove failing on the backup: file owned by a different user (e.g. upgrade run with sudo but .tmp owned by root from a previous run), read-only directory, or the file held open by another process.

Common situations: Mixed privileged/unprivileged upgrades leaving root-owned .tmp files; a leftover caddy.tmp held open by a crashed process.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/416a2843bb359ad7. Report an issue: GitHub.