hasura/graphql-engine · critical
rename old to exe: inconsistent state, re-install cli: %w
Error message
rename old to exe: inconsistent state, re-install cli: %w
What it means
The worst-case self-update failure: the current binary was renamed to '<exe>.old', then renaming the new binary into place failed, and the rollback rename (old -> exe) ALSO failed (cli/update/update.go:180). The CLI is left with no executable at its expected path; the error explicitly tells the user to re-install because the updater cannot recover automatically.
Source
Thrown at cli/update/update.go:180
err = os.Rename(exe, oldExe)
if err != nil {
return errors.E(op, fmt.Errorf("rename exe to old: %w", err))
}
// rename the new binary as the current binary
err = os.Rename(newExe, exe)
if err != nil {
// rename unsuccessful
//
// The filesystem is now in a bad state. We have successfully
// moved the existing binary to a new location, but we couldn't move the new
// binary to take its place. That means there is no file where the current executable binary
// used to be!
// Try to rollback by restoring the old binary to its original path.
rerr := os.Rename(oldExe, exe)
if rerr != nil {
// rolling back failed, ask user to re-install cli
return errors.E(op, fmt.Errorf(
"rename old to exe: inconsistent state, re-install cli: %w",
rerr))
}
// rolled back, throw update error
return errors.E(op, fmt.Errorf("rename new to exe: %w", err))
}
// rename success, remove the old binary
errRemove := os.Remove(oldExe)
// windows has trouble removing old binaries, so hide it instead
// it will be removed next time this code runs.
if errRemove != nil {
_ = hideFile(oldExe)
}
return nil
}View on GitHub (pinned to 724551b9ae)
Solutions
- Re-install the CLI using your original install method (install script, package manager, go install) — recovery by hand is only for experts.
- As a last resort, manually restore: mv '<exe>.old' back to the exe path if the .old file still exists.
- On Windows, exclude the CLI install directory from real-time antivirus scanning before updating again.
- Ensure stable permissions and disk space before retrying updates.
Example fix
# recovery when .old survived $ ls /usr/local/bin/cli* # see cli.old / .cli.new $ mv /usr/local/bin/cli.old /usr/local/bin/cli $ chmod +x /usr/local/bin/cli # then re-install properly
Defensive patterns
Strategy: fallback
Validate before calling
if _, err := os.Stat(exe); err != nil {
if _, oerr := os.Stat(exe + ".old"); oerr == nil {
// recovery possible: .old exists
}
} Try / catch
if err := update.ApplyUpdate(v); err != nil {
if strings.Contains(err.Error(), "inconsistent state, re-install cli") {
os.Rename(exe+".old", exe) // best-effort manual recovery
return fmt.Errorf("update broke install; restored from .old, please re-install: %w", err)
}
return err
} Prevention
- Run updates only when the system is stable (no concurrent AV scans, ample disk, steady power).
- Keep the original installer/package-manager command handy for quick reinstall.
- Backup or snapshot the binary before updating in critical environments.
When it happens
Trigger: ApplyUpdate where the second os.Rename(newExe, exe) fails (e.g. the .new file disappeared or was quarantined by antivirus) and the subsequent os.Rename(oldExe, exe) also fails (permissions changed, disk error, locked files).
Common situations: Antivirus quarantining the freshly downloaded .new binary mid-swap; disk filling or permissions changing between the two renames; power loss or forced process kill during the swap window leaving an inconsistent state.
Related errors
- rename exe to old: %w
- rename new to exe: %w
- could not rename/copy file from %q to %q: %w
- could not rename/copy directory %q to %q: %w
- saving downloaded file: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/4d3553ba67303945.
Report an issue: GitHub.