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
- Verify the new binary works: caddy version — the upgrade itself succeeded
- Delete the leftover backup with appropriate privileges: sudo rm -f /path/to/caddy.tmp
- Pass --keep-backup on future upgrades if you want the backup retained deliberately
- 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
- Pass --keep-backup when you want the rollback copy preserved intentionally
- Keep ownership of the binary directory consistent (always upgrade with the same privileges)
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
- backing up current binary: %v
- checking if default Caddyfile exists: %v
- reading config from file: %v
- reading default Caddyfile: %v
- reading environment file: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/416a2843bb359ad7.
Report an issue: GitHub.