matryer/xbar · error
unarchive
Error message
unarchive
What it means
Raised in Updater.downloadAndReplaceApp when archiver.Unarchive fails to extract the downloaded update archive into the app's directory. By this point the running app has already been renamed to the '.previous' path, so a failure here leaves the installation in a swapped-out state: the old build exists only under appPath + '.previous' and the update is not applied.
Source
Thrown at pkg/update/update.go:224
return errors.Wrap(err, "get executable")
}
appPath, err := appPathFromExecutable(executable)
if err != nil {
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.View on GitHub (pinned to d624239058)
Solutions
- Verify the downloaded archive is complete and not corrupted (check size/hash before unarchiving)
- Confirm the archive format is one the archiver library supports
- Check write permissions and free disk space in appPathDir
- On failure, restore the app by renaming the '.previous' copy back to appPath so the old version still runs
- Re-download the archive if it was truncated or tampered with
Defensive patterns
Strategy: fallback
Validate before calling
zr, err := zip.OpenReader(downloadedZipPath)
if err != nil {
return fmt.Errorf("downloaded asset is not a valid zip: %w", err)
}
zr.Close() Try / catch
err := u.Update()
if err != nil && strings.Contains(err.Error(), "unarchive") {
log.Printf("update archive invalid; re-downloading: %v", err)
return retryUpdate()
} Prevention
- Verify archive integrity (checksum) at publish time and after download
- Publish zips with standard deflate compression, no encryption
- Ensure no other processes lock files in the extraction directory
When it happens
Trigger: Calling Update() when the downloaded asset is a corrupt/truncated zip, is not actually a zip despite the extension, contains files with paths the extractor can't write (permissions, existing locked files), or the zip uses unsupported compression/encryption.
Common situations: Download interrupted earlier producing a partial zip; server returned an HTML error page saved with a .zip name; extracting over files locked by running processes on Windows; zips created with encryption or non-deflate compression.
Related errors
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/e9662a6550ec47fc.
Report an issue: GitHub.