github/copilot-sdk · error

creating install directory

Error message

creating install directory: %w

What it means

installAt creates the versioned install directory (with MkdirAll) before laying down the CLI binary and assets. If directory creation fails, the error is wrapped with this message. It prevents installation from proceeding without a writable target directory.

Solutions

  1. Check the wrapped err for the exact cause (EACCES, ENOTDIR, EROFS)
  2. Create the parent install dir with proper ownership/permissions (sudo mkdir + chown) or point the install dir at a user-writable location (e.g. under $HOME)
  3. If a file exists where the directory should be, remove or rename it
  4. Avoid read-only filesystems, or install to a writable volume

Example fix

// before
// installAt("/usr/local/lib/copilot", ...) fails with permission denied
// after
dir := os.Getenv("XDG_DATA_HOME")
if dir == "" { dir = filepath.Join(os.Getenv("HOME"), ".local", "share") }
path, err := installAt(filepath.Join(dir, "copilot"), version)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the install root is writable before installing
if err := os.MkdirAll(installRoot, 0755); err != nil { /* pick a writable dir */ }

Try / catch

// Go
path, err := installAt(dir, version)
var pe *fs.PathError
if err != nil && errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
	// fall back to a user-writable install location
}

Prevention

When it happens

Trigger: os.MkdirAll on the install path fails: parent dir not writable, path exists as a regular file, read-only filesystem, or SELinux/AppArmor denial.

Common situations: Installing into a system path like /usr/local/lib without sudo; install root pre-empted by a stale file with the same name; running in a read-only container filesystem; multi-user machines where another user owns the version directory.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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

Appendix: source

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

	cfg.RuntimeAssetsHash = cfg.LinuxMuslRuntimeAssetsHash
	return cfg
}

func isMusl() bool {
	out, _ := exec.Command("ldd", "--version").CombinedOutput()
	return strings.Contains(strings.ToLower(string(out)), "musl")
}

func installAt(installDir string) (string, error) {
	version := sanitizeVersion(config.Version)
	if version != "" {
		installDir = filepath.Join(installDir, version)
	}
	if linuxMuslBundle {
		installDir = filepath.Join(installDir, "linuxmusl")
	}
	if err := os.MkdirAll(installDir, 0755); err != nil {
		return "", fmt.Errorf("creating install directory: %w", err)
	}

	// Best effort to prevent concurrent installs.
	if release, _ := flock.Acquire(filepath.Join(installDir, ".copilot-cli.lock")); release != nil {
		defer release()
	}

	binaryName := "copilot"
	if runtime.GOOS == "windows" {
		binaryName += ".exe"
	}
	finalPath := filepath.Join(installDir, binaryName)

	if _, err := os.Stat(finalPath); err == nil {
		existingHash, err := hashFile(finalPath)
		if err != nil {
			return "", fmt.Errorf("hashing existing binary: %w", err)
		}

View on GitHub (pinned to cd8cf15dc3)