github/copilot-sdk · error

existing hash mismatch

Error message

existing %s hash mismatch

What it means

installVerifiedFile refuses to overwrite an existing file whose SHA-256 hash differs from the hash of the content about to be installed. This guards against clobbering a modified or foreign binary with embedded assets. The message includes the asset label (e.g. "runtime asset").

Solutions

  1. Delete the modified file at the target path and re-run the install so the verified embedded version is written.
  2. Check which version originally installed the file; align install directories per version if you need multiple versions.
  3. If the modification is intentional, stop installing over that path — point installDir at a dedicated directory.

Example fix

// before
client.InstallAt("/opt/shared/cli") // contains a patched binary
// after
os.Remove("/opt/shared/cli/cli-server")
client.InstallAt("/opt/shared/cli")
Defensive patterns

Strategy: try-catch

Try / catch

if err := client.InstallAt(dir); err != nil {
    if strings.Contains(err.Error(), "hash mismatch") {
        // file was modified on disk; prompt user to delete it and reinstall
    }
}

Prevention

When it happens

Trigger: The file at path exists and hashFile succeeds, but bytes.Equal(existingHash, expectedHash) is false during any call from installRuntimeAssets/installRuntimePair — i.e. the on-disk file differs from the embedded content.

Common situations: A user or patch script edited the installed binary, a different library version was previously installed into the same directory, or the file was partially written by a failed earlier install.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

	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
	}

	tmp, err := os.CreateTemp(filepath.Dir(path), ".copilot-runtime-pair-*.tmp")
	if err != nil {
		return fmt.Errorf("creating temporary %s: %w", label, err)

View on GitHub (pinned to cd8cf15dc3)