multica-ai/multica · error
move running binary aside
Error message
move running binary aside: %w
What it means
Windows-only replaceBinary failure: os.Rename(exePath, exePath+".old") could not move the currently running executable aside. Windows locks a running .exe against delete/rename-in-place, so this fires when something holds an unexpected handle on the binary, the directory denies write access, or the previously removed .old path is still locked by another process.
Solutions
- Stop all multica processes (taskmgr / Get-Process multica) and retry the update
- Add an AV exclusion for the install directory, or retry after a few seconds so the AV scan handle is released
- Move the install to a user-writable directory (or run the update elevated if under Program Files)
- If a stale .old file is the problem, reboot (releases the lock) so CleanupStaleUpdateArtifacts can remove it, then update
Defensive patterns
Strategy: retry
Validate before calling
// Before replacing, check for other running instances of this exe.
func otherInstancesRunning() bool {
self, _ := os.Executable()
procs, _ := gops.Processes() // or enumerate via tasklist on Windows
for _, p := range procs {
if exe, err := p.Exe(); err == nil && strings.EqualFold(exe, self) && p.Pid() != os.Getpid() {
return true
}
}
return false
} Try / catch
Catch sharing-violation errors (syscall.ERROR_SHARING_VIOLATION via errors.As on *os.LinkError/*os.PathError) and retry the rename 2-3 times with a short backoff before giving up.
Prevention
- Run exactly one daemon per install path
- Add AV exclusions for the multica install directory
- Install in a user-writable directory, not Program Files, unless elevated
When it happens
Trigger: Running the self-update while a second multica instance (or a crashed child process) still holds the exe open, antivirus scanning the binary at the moment of rename, insufficient NTFS permissions on the install directory, or the exe living on a read-only/network mount.
Common situations: Two daemons started from the same install path, AV/EDR agents briefly locking freshly downloaded binaries, running from a mounted share, or install dirs under Program Files without elevation.
Related errors
- install new binary: (and failed to restore: )
- replace binary
- install new binary
- rename temp to
- brew upgrade failed
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/55ab966b39367b15.
Report an issue: GitHub.
Appendix: source
Thrown at server/internal/cli/update_windows.go:36
// replaceBinary swaps the running executable for the freshly-downloaded one.
// Windows holds an exclusive handle on a running .exe, so the rename-over
// pattern used on Unix fails with "Access is denied". Instead:
// 1. Clear any stale leftover from a previous update.
// 2. Move the running executable aside to exePath+".old".
// 3. Rename the new binary into place.
// 4. If step 3 fails, restore the original so the user isn't stranded.
//
// The leftover .old file is cleaned up on next startup via
// CleanupStaleUpdateArtifacts.
func replaceBinary(tmpPath, exePath string) error {
oldPath := exePath + oldBinarySuffix
// Best-effort cleanup; if this fails (file still locked) the next Rename
// will surface a useful error.
_ = os.Remove(oldPath)
if err := os.Rename(exePath, oldPath); err != nil {
return fmt.Errorf("move running binary aside: %w", err)
}
if err := os.Rename(tmpPath, exePath); err != nil {
// Restore so the user isn't left without a multica.exe.
if rerr := os.Rename(oldPath, exePath); rerr != nil {
return fmt.Errorf("install new binary: %w (and failed to restore: %v)", err, rerr)
}
return fmt.Errorf("install new binary: %w", err)
}
return nil
}
// CleanupStaleUpdateArtifacts removes leftover `.old` binaries from previous
// updates. Windows can't delete a running .exe, so a prior update may have
// left one behind; once the user restarts, this call reclaims the space.
func CleanupStaleUpdateArtifacts() {
exePath, err := selfexec.Resolve()View on GitHub (pinned to 2c0912b6ec)