{"record":{"id":"5492bc5066d93ba2","repo":"multica-ai/multica","slug":"install-new-binary-w-and-failed-to-restore-v","errorCode":null,"errorMessage":"install new binary: %w (and failed to restore: %v)","messagePattern":"install new binary: %w \\(and failed to restore: (.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/internal/cli/update_windows.go","lineNumber":42,"sourceCode":"//  4. If step 3 fails, restore the original so the user isn't stranded.\n//\n// The leftover .old file is cleaned up on next startup via\n// CleanupStaleUpdateArtifacts.\nfunc replaceBinary(tmpPath, exePath string) error {\n\toldPath := exePath + oldBinarySuffix\n\n\t// Best-effort cleanup; if this fails (file still locked) the next Rename\n\t// will surface a useful error.\n\t_ = os.Remove(oldPath)\n\n\tif err := os.Rename(exePath, oldPath); err != nil {\n\t\treturn fmt.Errorf(\"move running binary aside: %w\", err)\n\t}\n\n\tif err := os.Rename(tmpPath, exePath); err != nil {\n\t\t// Restore so the user isn't left without a multica.exe.\n\t\tif rerr := os.Rename(oldPath, exePath); rerr != nil {\n\t\t\treturn fmt.Errorf(\"install new binary: %w (and failed to restore: %v)\", err, rerr)\n\t\t}\n\t\treturn fmt.Errorf(\"install new binary: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// CleanupStaleUpdateArtifacts removes leftover `.old` binaries from previous\n// updates. Windows can't delete a running .exe, so a prior update may have\n// left one behind; once the user restarts, this call reclaims the space.\nfunc CleanupStaleUpdateArtifacts() {\n\texePath, err := selfexec.Resolve()\n\tif err != nil {\n\t\treturn\n\t}\n\tif resolved, err := filepath.EvalSymlinks(exePath); err == nil {\n\t\texePath = resolved\n\t}","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update_windows.go#L24-L60","documentation":"Windows-only replaceBinary failure where BOTH renames failed: moving the new binary into place failed AND rolling the original back from the .old name failed. The install is now in a broken state — no exe exists at exePath (the original sits at exePath+'.old'), so multica.exe cannot start until it is restored manually.","triggerScenarios":"The new binary at tmpPath became locked (AV grabbed the freshly downloaded file between the two renames) at the same time the .old file was also locked (another process still running the old image), or the directory ACL changed mid-update.","commonSituations":"Aggressive AV/EDR scanning new binaries while a second multica process still runs the old one; transient filesystem errors on network mounts; disk-full conditions on the install volume.","solutions":["Manually restore: rename multica.exe.old back to multica.exe in the install directory","Terminate every process holding either file (Resource Monitor > CPU > Associated Handles) or simply reboot, then restore/reinstall","Add AV exclusions for the install directory before retrying the update","Reinstall from the release artifact if the .old file is gone or corrupt"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Before update: verify both source and destination renames are likely to succeed.\nfunc canReplace(tmpPath, exePath string) error {\n    if _, err := os.Stat(tmpPath); err != nil {\n        return fmt.Errorf(\"new binary missing: %w\", err)\n    }\n    if fi, err := os.Stat(filepath.Dir(exePath)); err != nil || !fi.IsDir() {\n        return fmt.Errorf(\"install directory unavailable: %w\", err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"On this error, immediately print a recovery instruction: 'rename <exePath>.old back to <exePath> or reinstall' — the app must not continue silently with no exe in place.","preventionTips":["Stop all instances of the binary before updating","Keep AV exclusions on both install and temp directories","Have the installer/updater write a recovery script next to the exe before starting the swap"],"tags":["windows","self-update","file-lock","broken-install"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}