multica-ai/multica · error

install new binary: %w

Error message

install new binary: %w

What it means

Windows-only replaceBinary failure where the new binary could not be moved into place, but the rollback succeeded: the original executable was restored from the .old name, so the installation is intact at the previous version. Typical root causes mirror 865 (AV lock on the fresh file, permissions, disk state) but recovery already happened.

Source

Thrown at server/internal/cli/update_windows.go:44

// 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()
	if err != nil {
		return
	}
	if resolved, err := filepath.EvalSymlinks(exePath); err == nil {
		exePath = resolved
	}
	_ = os.Remove(exePath + oldBinarySuffix)
}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Retry the update — transient sharing violations usually clear within seconds
  2. Add an AV exclusion for the install and temp directories if it repeats
  3. Ensure the temp binary lands on the same volume as the install (avoids cross-volume rename edge cases)
  4. Check disk space and directory permissions on the install path
Defensive patterns

Strategy: retry

Validate before calling

// Ensure temp file is on the same volume as the exe before attempting replace.
tmpDir := filepath.Dir(exePath)
tmp, err := os.CreateTemp(tmpDir, "multica-update-*")
if err != nil {
    return fmt.Errorf("stage download beside exe: %w", err)
}

Try / catch

Since the original was restored, the safe pattern is: log 'update failed, still on version X', wait a few seconds, retry the whole download+replace once. Check ERROR_SHARING_VIOLATION to distinguish AV locks.

Prevention

When it happens

Trigger: Self-update where os.Rename(tmpPath, exePath) fails — most commonly antivirus holding the just-downloaded temp binary, the temp file being on a different volume with restrictive ACLs, or the destination briefly locked by a scanner — and the restore rename then succeeds.

Common situations: First update attempt on machines with real-time AV scanning; temp dir on a different drive than the install; transient sharing violations on Windows.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/93fff04d2efcb526. Report an issue: GitHub.