chenhg5/cc-connect · error

chmod new binary: %w

Error message

chmod new binary: %w

What it means

After successfully copying the new binary, replaceExecutable sets executable permissions with os.Chmod(target, 0o755). If the chmod call fails the update aborts with "chmod new binary: %w". The new binary content is in place but may not be executable, and the backup file is intentionally left on disk because os.Remove(backup) is only reached on success.

Source

Thrown at cmd/cc-connect/update.go:451

	// On Windows, rename over a running exe is not possible directly.
	// Move old binary aside, then move new one in.
	backup := target + ".old"
	os.Remove(backup)

	if err := os.Rename(target, backup); err != nil {
		return fmt.Errorf("backup old binary: %w", err)
	}

	if err := copyFile(src, target); err != nil {
		// Attempt to restore
		if restoreErr := os.Rename(backup, target); restoreErr != nil {
			slog.Warn("update: failed to restore old binary after copy error", "error", restoreErr)
		}
		return fmt.Errorf("install new binary: %w", err)
	}

	if err := os.Chmod(target, 0o755); err != nil {
		return fmt.Errorf("chmod new binary: %w", err)
	}

	os.Remove(backup)
	return nil
}

func copyFile(src, dst string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the wrapped chmod error; if it's permission-denied, take ownership of the binary: sudo chown $(whoami) <target>.
  2. If the filesystem doesn't support permission bits (WSL /mnt/c, FAT/exFAT), move the install location to a native Linux filesystem.
  3. Manually chmod +x the target binary and verify it runs (cc-connect --version); if OK, remove the stale backup file.
  4. Avoid install directories mounted with noexec; relocate the binary to e.g. /usr/local/bin or ~/.local/bin.
  5. Re-run `cc-connect update` after fixing the environment to complete cleanup of the backup file.

Example fix

// before: binary on a mount without POSIX perms
BinaryPath = "/mnt/c/tools/cc-connect"

// after: install to a Linux-native path
BinaryPath = "/usr/local/bin/cc-connect"
Defensive patterns

Strategy: validation

Validate before calling

st, err := os.Stat(target)
if err != nil { return err }
if st.Mode().Perm()&0o755 == 0 {
    // filesystem may not support chmod; test with a temp file first
    tmp := target + ".chmodtest"
    os.WriteFile(tmp, []byte("x"), 0o644)
    _, err = os.Stat(tmp)
    os.Remove(tmp)
    if err != nil { return fmt.Errorf("install dir unusable: %w", err) }
}

Try / catch

if err := runUpdate(); err != nil {
    if strings.Contains(err.Error(), "chmod new binary") {
        slog.Warn("chmod failed; binary may lack +x", "err", err)
        _ = os.Chmod(target, 0o755) // manual recovery attempt
    }
}

Prevention

When it happens

Trigger: `cc-connect update` via runUpdate; the copy of the new binary succeeded but os.Chmod(target, 0o755) returned an error — e.g. the filesystem doesn't support chmod (some network mounts, Windows FAT/NTFS via WSL), or the user lacks ownership of the newly created file.

Common situations: Updating a binary installed in a directory mounted with 'noexec' or via a share that doesn't support POSIX permissions; running under WSL against /mnt/c; the install directory owned by another user after a previous sudo install.

Understand the failure class

Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a5d207b449c4605f. Report an issue: GitHub.