hasura/graphql-engine · error

rename exe to old: %w

Error message

rename exe to old: %w

What it means

During ApplyUpdate's atomic swap, os.Rename(exe, oldExe) — renaming the current binary to '<exe>.old' — failed (cli/update/update.go:164). This happens before the new binary is moved into place, so the installation is still intact; typical causes are lacking write permission on the directory or the running executable being immutable/locked.

Source

Thrown at cli/update/update.go:164

		return errors.E(op, fmt.Errorf("download asset: %w", err))
	}

	// get the downloaded binary name and build the absolute path
	newExe := asset.Name()

	// build name and absolute path for saving old binary
	oldExeName := "." + exeName + ".old"
	oldExe := filepath.Join(exePath, oldExeName)

	// delete any existing old binary file - this is necessary on Windows for two reasons:
	// 1. after a successful update, Windows can't remove the .old file because the process is still running
	// 2. windows rename operations fail if the destination file already exists
	_ = os.Remove(oldExe)

	// rename the current binary as old binary
	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))

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Ensure write permission on the directory containing the binary (or rerun the update with elevated privileges on macOS/Windows).
  2. Delete a stale '<exe>.old' if it exists and the rename reports a conflict (preparation normally removes it, but check manually).
  3. Disable/exclude the CLI binary from antivirus locking on Windows.
  4. Avoid installing the binary on network filesystems where rename semantics are unreliable.

Example fix

# before
$ cli update
# error: rename exe to old: permission denied

# after (unix)
$ sudo chown $(whoami) /usr/local/bin/cli
$ cli update
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(exe)
if werr := testWritable(dir); werr != nil {
    return fmt.Errorf("cannot update: %w (try adjusting permissions)", werr)
}

Try / catch

if err := update.ApplyUpdate(v); err != nil {
    if strings.Contains(err.Error(), "rename exe to old") {
        // installation still intact, safe to keep using current version
        log.Printf("update aborted before swap: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: ApplyUpdate where the install directory is not writable by the current user, another process holds a mandatory lock on the binary, or the filesystem does not allow renaming a running executable (some NFS/Windows configurations).

Common situations: CLI installed in /usr/local/bin and update run without sudo; Windows antivirus scanning the exe at the moment of rename; binary on a read-only or network mount.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/822429007165647a. Report an issue: GitHub.