caddyserver/caddy · error

backing up current binary: %v

Error message

backing up current binary: %v

What it means

Thrown by caddy upgrade/add-package after a custom build has been downloaded from caddyserver.com, when os.Rename fails while moving the current executable to '<exec>.tmp' before overwriting it. The upgrade aborts before anything is modified, so the original binary is untouched. The underlying cause is almost always filesystem permissions or the executable being locked by a running process.

Source

Thrown at cmd/packagesfuncs.go:169

	for _, pkgInfo := range pluginPkgs {
		qs.Add("p", pkgInfo.String())
	}

	// initiate the build
	resp, err := downloadBuild(qs)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("download failed: %v", err)
	}
	defer resp.Body.Close()

	// back up the current binary, in case something goes wrong we can replace it
	backupExecPath := thisExecPath + ".tmp"
	l.Info("build acquired; backing up current executable",
		zap.String("current_path", thisExecPath),
		zap.String("backup_path", backupExecPath))
	err = os.Rename(thisExecPath, backupExecPath)
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("backing up current binary: %v", err)
	}
	defer func() {
		if err != nil {
			err2 := os.Rename(backupExecPath, thisExecPath)
			if err2 != nil {
				l.Error("restoring original executable failed; will need to be restored manually",
					zap.String("backup_path", backupExecPath),
					zap.String("original_path", thisExecPath),
					zap.Error(err2))
			}
		}
	}()

	// download the file; do this in a closure to close reliably before we execute it
	err = writeCaddyBinary(thisExecPath, &resp.Body, thisExecStat)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err
	}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Re-run with sufficient privileges: 'sudo caddy upgrade' (Linux/macOS) or an elevated shell on Windows
  2. Stop all running Caddy instances before upgrading (on Windows the exe is locked while running)
  3. Verify write permission on the binary's directory: ls -ld $(dirname $(which caddy)); chmod or chown if needed
  4. Remove a stale read-only backup: rm -f $(which caddy).tmp
  5. If on a read-only filesystem, copy the binary to a writable location, upgrade there, then move it back

Example fix

# before
caddy upgrade
# error: backinging up current binary: rename /usr/local/bin/caddy /usr/local/bin/caddy.tmp: permission denied

# after
sudo caddy upgrade
Defensive patterns

Strategy: validation

Validate before calling

# before running caddy upgrade
EXEC="$(command -v caddy)"
DIR="$(dirname "$EXEC")"
[ -w "$DIR" ] || { echo "not writable: $DIR (use sudo)"; exit 1; }
[ -f "$EXEC.tmp" ] && rm -f "$EXEC.tmp"
df -h "$DIR" | tail -1   # confirm space
# on Windows: stop the caddy service first (sc stop caddy)

Prevention

When it happens

Trigger: Running 'caddy upgrade' or 'caddy add-package' when: the directory containing the binary is not writable by the current user (e.g. /usr/bin owned by root and running unprivileged); on Windows, a caddy instance is still running so the exe file is locked; a stale '<exec>.tmp' exists as read-only; the filesystem is read-only (container, mounted volume).

Common situations: Installing caddy via a package manager into /usr/bin or /usr/local/bin and running 'caddy upgrade' without sudo; forgetting to stop systemd caddy service on Windows; running inside a Docker container where the binary lives on a read-only layer.

Related errors


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