github/copilot-sdk · error

hashing existing

Error message

hashing existing %s: %w

What it means

installVerifiedFile first hashes an already-existing file at the target path with hashFile to decide whether it can be reused or must be rewritten. This error wraps a failure of that hashing (the file could not be opened/read), not a hash comparison failure.

Solutions

  1. Fix read permissions on the existing file at the target path (chmod/chown so the current user can read it).
  2. Delete the existing file manually and re-run the install.
  3. Close/whitelist security software that may lock the file, then retry.

Example fix

// before
$ ls -l ~/.local/bin/cli  # -rw------- root root
// after
$ sudo rm ~/.local/bin/cli && client.InstallAt(installDir)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(target); err == nil {
    if f, err := os.Open(target); err != nil {
        // cannot read existing file: fix perms or remove before install
    } else {
        f.Close()
    }
}

Try / catch

if err := client.InstallAt(dir); err != nil {
    if strings.Contains(err.Error(), "hashing existing") {
        // remove the unreadable file and retry the install
    }
}

Prevention

When it happens

Trigger: The destination path exists (os.Stat succeeds) but hashFile(path) fails — e.g. the file exists but cannot be opened for reading due to permissions, or it disappears between Stat and read.

Common situations: A previous install left a root-owned or read-only binary at the target path; a race where another process removes the file between Stat and hashing; antivirus/EDR locking the file on Windows.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/10c3c191eab801a4. Report an issue: GitHub.

Appendix: source

Thrown at go/internal/embeddedcli/embeddedcli.go:448

}

func installRuntimePair(installDir string) (string, error) {
	nodePath := filepath.Join(installDir, "runtime.node")
	if err := installVerifiedFile(nodePath, config.RuntimeNode, config.RuntimeNodeHash, 0644, "runtime.node"); err != nil {
		return "", err
	}
	wrapperPath := filepath.Join(installDir, runtimeExecutableName())
	if err := installVerifiedFile(wrapperPath, config.RuntimeExecutable, config.RuntimeExecutableHash, 0755, "runtime wrapper"); err != nil {
		return "", err
	}
	return wrapperPath, nil
}

func installVerifiedFile(path string, reader io.Reader, expectedHash []byte, mode os.FileMode, label string) error {
	if _, err := os.Stat(path); err == nil {
		existingHash, err := hashFile(path)
		if err != nil {
			return fmt.Errorf("hashing existing %s: %w", label, err)
		}
		if !bytes.Equal(existingHash, expectedHash) {
			return fmt.Errorf("existing %s hash mismatch", label)
		}
		if runtime.GOOS != "windows" && mode.Perm()&0111 != 0 {
			info, err := os.Stat(path)
			if err != nil {
				return fmt.Errorf("checking existing %s permissions: %w", label, err)
			}
			if info.Mode().Perm()&0111 == 0 {
				if err := os.Chmod(path, info.Mode().Perm()|mode.Perm()&0111); err != nil {
					return fmt.Errorf("restoring existing %s permissions: %w", label, err)
				}
			}
		}
		return nil
	}

View on GitHub (pinned to cd8cf15dc3)