chenhg5/cc-connect · error
backup old binary: %w
Error message
backup old binary: %w
What it means
replaceBinary preserves the running binary by renaming it to execPath + ".old" before installing the new one; if os.Rename fails the temp file is removed and the error wrapped as "backup old binary: %w". Cross-device renames are the classic cause since rename cannot move across filesystems.
Source
Thrown at core/updater.go:279
if _, err := tmpFile.Write(newBinary); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return fmt.Errorf("write new binary: %w", err)
}
tmpFile.Close()
if err := os.Chmod(tmpPath, 0o755); err != nil {
os.Remove(tmpPath)
return fmt.Errorf("chmod: %w", err)
}
oldPath := execPath + ".old"
os.Remove(oldPath)
if err := os.Rename(execPath, oldPath); err != nil {
os.Remove(tmpPath)
return fmt.Errorf("backup old binary: %w", err)
}
if err := os.Rename(tmpPath, execPath); err != nil {
// Try to restore
if restoreErr := os.Rename(oldPath, execPath); restoreErr != nil {
slog.Error("updater: failed to restore old binary after install failed", "error", restoreErr)
}
return fmt.Errorf("install new binary: %w", err)
}
// Don't remove .old file on Linux - the running process may still need it
// for os.Executable() to work correctly after restart.
// The .old file will be overwritten on next update.
slog.Info("updater: binary replaced successfully", "path", execPath)
return nil
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Check for a leftover <binary>.old that is a directory or owned oddly (ls -la next to the binary) and remove/fix it, then retry.
- Ensure the running user can write to the binary's directory (renaming requires directory write permission): sudo chown/chmod as needed.
- Remove the stale .old file first: sudo rm -f /path/to/cc-connect.old — the updater also tries os.Remove(oldPath) before renaming, but only as the same (possibly unprivileged) user.
- Check audit logs (SELinux/apparmor) if permission is denied unexpectedly and adjust policy.
- Restart from the current binary and retry; if deploys delete binaries concurrently, serialize deploys with the updater.
Example fix
# before ls -la /opt/cc-connect drwxr-xr-x cc-connect.old # directory blocks rename # after sudo rm -rf /opt/cc-connect/cc-connect.old && sudo cc-connect update
Defensive patterns
Strategy: validation
Validate before calling
oldPath := execPath + ".old"
if info, err := os.Lstat(oldPath); err == nil && info.IsDir() {
return fmt.Errorf("%s is a directory; remove it before updating", oldPath)
}
os.Remove(oldPath) // pre-clean like the updater does Try / catch
if err := selfUpdate(); err != nil {
if strings.Contains(err.Error(), "backup old binary") {
// remove stale cc-connect.old, ensure dir write permission, retry
}
} Prevention
- Never leave a cc-connect.old directory in the install path
- Grant the run user write permission on the install directory
- Serialize deploys with self-updates; don't delete binaries concurrently
When it happens
Trigger: SelfUpdate -> replaceBinary: os.Rename(execPath, oldPath) failed — the .old target is a directory, the binary's directory is on a filesystem where rename of the open executable is restricted (e.g. some Windows lock semantics in emulated environments), permission denied on the directory (write permission needed to rename within it), or the path disappeared after EvalSymlinks.
Common situations: A stale cc-connect.old directory (not file) left by a previous manual intervention; directory made read-only after the temp file was created via different privileges; SELinux policy blocking rename of a running executable; execPath deleted concurrently by a deploy script.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- install new binary: %w
- get executable path: %w
- resolve symlinks: %w
- create temp file: %w
- write new binary: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/b8cd73817753f56f.
Report an issue: GitHub.