matryer/xbar · warning
remove previous
Error message
remove previous
What it means
os.RemoveAll of the '<appPath>.previous' backup failed after the new version was successfully extracted; the error is wrapped as 'remove previous'. The update itself is in place — this is only cleanup of the old binary backup.
Source
Thrown at pkg/update/update.go:228
return errors.Wrap(err, "find app path")
}
appPathDir := filepath.Dir(appPath)
appPreviousPath := appPath + ".previous"
err = os.Rename(appPath, appPreviousPath)
if err != nil {
_, statErr := os.Stat(appPath)
// not exist is ok, just ignore it
if !os.IsNotExist(statErr) {
return errors.Wrap(err, "rename existing app")
}
}
err = archiver.Unarchive(f.Name(), appPathDir)
if err != nil {
return errors.Wrap(err, "unarchive")
}
err = os.RemoveAll(appPreviousPath)
if err != nil {
return errors.Wrap(err, "remove previous")
}
return nil
}
// Release is a GitHub release.
type Release struct {
TagName string `json:"tag_name"`
Assets []Asset `json:"assets"`
Body string `json:"body"`
CreatedAtString string `json:"created_at"`
CreatedAt time.Time `json:"created_at_time"`
}
// Asset is a file within a Release on GitHub.
type Asset struct {
Name string `json:"name"`
BrowserDownloadURL string `json:"browser_download_url"`
}View on GitHub (pinned to d624239058)
Solutions
- Manually delete the '<appPath>.previous' file once no process holds it — the update is already applied.
- Retry the update; leftover .previous files don't affect the running version.
- Ensure antivirus/backup tools exclude the app directory so cleanup files can be removed.
- Treat this as a warning-level cleanup issue and log instead of failing the update flow.
Example fix
// before
err = os.RemoveAll(appPreviousPath)
if err != nil {
return errors.Wrap(err, "remove previous")
}
// after
if err := os.RemoveAll(appPreviousPath); err != nil {
log.Printf("warning: cleanup of %s failed: %v", appPreviousPath, err)
} Defensive patterns
Strategy: fallback
Validate before calling
prev := appPath + ".previous"
if _, err := os.Stat(prev); err == nil {
if err := os.Remove(prev); err != nil {
log.Printf("previous backup still locked, cleanup deferred: %v", err)
}
} Try / catch
err := u.Update()
if err != nil && strings.Contains(err.Error(), "remove previous") {
log.Printf("update applied but backup cleanup failed; safe to ignore/delete %s.previous: %v", appPath, err)
return nil
} Prevention
- Exclude the install dir from antivirus/backup locking
- Clean stale .previous files on the next app startup
- Log-and-continue for post-success cleanup failures instead of failing the update
When it happens
Trigger: Calling Update() when the .previous file cannot be deleted — locked by another process (Windows/AV), read-only, or permission denied in the app directory.
Common situations: Antivirus or backup software holding the .previous file; read-only mount; the .previous path is a non-empty directory owned by another user; Windows delayed file release after rename.
Related errors
- create directory %s for plugin
- create plugin file %s
- set executable permission on plugin entry point
- ReadDir
- WriteFile
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/4ae1690de1d02e15.
Report an issue: GitHub.