github/copilot-sdk · error
failed to chmod binary
Error message
failed to chmod binary: %w
What it means
On non-Windows targets (binary name not ending in .exe), the bundler chmods the extracted binary to 0755 so it is executable. If os.Chmod fails, this error wraps the failure. The binary exists but cannot yet be marked executable.
Solutions
- Ensure the destination filesystem supports POSIX permission changes (avoid FAT/exFAT/overlay mounts).
- Fix ownership of the extracted file (sudo chown) or clean stale build dirs from prior privileged runs.
- Run the build as a user with write permission on destDir.
- Move TMPDIR/destDir to a normal local ext4/APFS filesystem.
Example fix
// before: destDir inside a read-only container layer // after: use a writable location destDir = filepath.Join(os.TempDir(), "bundler-cli")
Defensive patterns
Strategy: validation
Validate before calling
// verify permission changes are possible on destDir
probe := filepath.Join(destDir, ".chmod-probe")
os.WriteFile(probe, nil, 0o644)
if err := os.Chmod(probe, 0o755); err != nil {
return fmt.Errorf("filesystem %s does not support chmod: %w", destDir, err)
}
os.Remove(probe) Try / catch
if err := buildBundle(...); err != nil {
if strings.Contains(err.Error(), "failed to chmod binary") {
moveDestToLocalFS(); retry()
}
return err
} Prevention
- Build on POSIX filesystems (ext4/APFS) rather than FAT/exFAT/network mounts.
- Run builds as a user owning the output directory.
- Clean up artifacts from previous sudo runs to avoid ownership conflicts.
- Point TMPDIR at a writable local path.
When it happens
Trigger: os.Chmod(binaryPath, 0755) returns non-nil — read-only filesystem, ownership mismatch, or immutable/ACL-restricted destination file.
Common situations: destDir on a mounted volume with noexec/no-permission changes (some Windows mounts, FAT/exFAT, container read-only layer); file owned by another user after a sudo-run previous build.
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
- restoring existing permissions
- Published runtime wrapper is not a non-empty executable…
- Failed to make Copilot CLI executable:
- approveAll cannot be used when managed settings are enabled
- CreateSessionFSProvider is required in session config when…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/ba233191eb5eff76.
Report an issue: GitHub.
Appendix: source
Thrown at go/cmd/bundler/main.go:1060
wrapperName := runtimeWrapperName(binaryName)
if err := extractFileFromTarball(
tarballPath,
destDir,
"package/prebuilds/"+runtimePlatform+"/"+wrapperName,
binaryName,
); err != nil {
return "", "", fmt.Errorf("failed to extract runtime wrapper compatibility entrypoint: %w", err)
}
// Verify binary exists
if _, err := os.Stat(binaryPath); err != nil {
return "", "", fmt.Errorf("binary not found after extraction: %w", err)
}
// Make executable on Unix
if !strings.HasSuffix(binaryName, ".exe") {
if err := os.Chmod(binaryPath, 0755); err != nil {
return "", "", fmt.Errorf("failed to chmod binary: %w", err)
}
}
stat, err := os.Stat(binaryPath)
if err != nil {
return "", "", fmt.Errorf("failed to stat binary: %w", err)
}
sizeMB := float64(stat.Size()) / 1024 / 1024
fmt.Printf("Downloaded %s (%.1f MB)\n", binaryName, sizeMB)
return binaryPath, tarballPath, nil
}
// extractCLILicense writes the license from the verified release package next to outputPath.
func extractCLILicense(tarballPath, outputPath string) error {
outputDir := filepath.Dir(outputPath)
if outputDir == "" {
outputDir = "."View on GitHub (pinned to cd8cf15dc3)