{"record":{"id":"85a08ec4c20e9a90","repo":"matryer/xbar","slug":"rename-existing-app","errorCode":null,"errorMessage":"rename existing app","messagePattern":"rename existing app","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/update/update.go","lineNumber":219,"sourceCode":"\t\treturn errors.Wrap(err, \"download asset\")\n\t}\n\tf.Close()\n\texecutable, err := u.GetExecutable()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get executable\")\n\t}\n\tappPath, err := appPathFromExecutable(executable)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"find app path\")\n\t}\n\tappPathDir := filepath.Dir(appPath)\n\tappPreviousPath := appPath + \".previous\"\n\terr = os.Rename(appPath, appPreviousPath)\n\tif err != nil {\n\t\t_, statErr := os.Stat(appPath)\n\t\t// not exist is ok, just ignore it\n\t\tif !os.IsNotExist(statErr) {\n\t\t\treturn errors.Wrap(err, \"rename existing app\")\n\t\t}\n\t}\n\terr = archiver.Unarchive(f.Name(), appPathDir)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"unarchive\")\n\t}\n\terr = os.RemoveAll(appPreviousPath)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"remove previous\")\n\t}\n\treturn nil\n}\n\n// Release is a GitHub release.\ntype Release struct {\n\tTagName         string    `json:\"tag_name\"`\n\tAssets          []Asset   `json:\"assets\"`\n\tBody            string    `json:\"body\"`","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/update/update.go#L201-L237","documentation":"os.Rename of the current app binary to '<appPath>.previous' failed and the app path still exists (the os.IsNotExist check on statErr failed), so the error is wrapped as 'rename existing app'. This means the old binary could not be moved aside before unarchiving the new version.","triggerScenarios":"Calling Update() when the app file is locked by another process (Windows file locking), lives on a different filesystem than needed, or the app directory is not writable.","commonSituations":"Windows: the running exe is locked by antivirus or another instance; Unix: read-only mount or permission denied on the app directory; the appPath is a directory rather than a file.","solutions":["Ensure no other instance of the app or antivirus is holding the binary open, then retry.","Verify write/create permissions on the directory containing the executable.","On Windows, rename after the process exits (external updater) or use a move-and-restart helper.","Check that appPath is a regular file on a filesystem supporting rename."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"appDir := filepath.Dir(appPath)\nif fi, err := os.Stat(appDir); err != nil || !fi.IsDir() {\n\treturn fmt.Errorf(\"app dir missing: %v\", err)\n}\nprobe := filepath.Join(appDir, \".write-test\")\nif err := os.WriteFile(probe, nil, 0o644); err != nil {\n\treturn fmt.Errorf(\"app dir not writable: %w\", err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"err := u.Update()\nif err != nil && strings.Contains(err.Error(), \"rename existing app\") {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn fmt.Errorf(\"close all app instances and retry: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Ensure only one instance of the app runs during updates","Whitelist the install dir in antivirus on Windows","Install to a user-writable location, not read-only system paths"],"tags":["filesystem","rename","permissions"],"backgroundTag":"file-rename-failed","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}