github/copilot-sdk · error

checking existing permissions

Error message

checking existing %s permissions: %w

What it means

When an existing file matches the expected hash, installVerifiedFile still ensures it is executable on non-Windows platforms. This error wraps an os.Stat failure that occurs while re-checking the existing file's permissions after the hash check succeeded.

Solutions

  1. Serialize installs — don't run two installs into the same installDir concurrently.
  2. Re-run the install; the file will be rewritten since it no longer exists.
  3. Check what external process (e.g. a cleaner/AV) removes files from the install directory.
Defensive patterns

Strategy: retry

Try / catch

err := client.InstallAt(dir)
if err != nil && strings.Contains(err.Error(), "checking existing") {
    time.Sleep(100 * time.Millisecond)
    err = client.InstallAt(dir) // transient race: file vanished mid-install
}

Prevention

When it happens

Trigger: os.Stat(path) fails in the permission-restoration branch — the file was removed or became inaccessible between the initial Stat/hashFile and this second Stat.

Common situations: A concurrent process deleting or replacing the installed binary mid-install; a race between two simultaneous installs into the same directory.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

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

	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)
	}
	tmpPath := tmp.Name()
	h := sha256.New()
	_, err = io.Copy(io.MultiWriter(tmp, h), reader)
	if err1 := tmp.Chmod(mode); err1 != nil && err == nil {

View on GitHub (pinned to cd8cf15dc3)