github/copilot-sdk · warning

failed to stat binary

Error message

failed to stat binary: %w

What it means

After making the binary executable, the bundler stats it again to report its size in MB before returning. If this second os.Stat fails, this error wraps it. The binary is in place, but its final metadata could not be read.

Solutions

  1. Re-run the build; this is nearly always a race with an external process.
  2. Disable or configure temp-dir cleanup/AV services that touch destDir during builds.
  3. Use a private per-build destination directory to avoid interference.
  4. Check filesystem health if the error reproduces consistently.

Example fix

// before: shared temp dir prone to cleanup
destDir := filepath.Join("/tmp", "shared-cli")

// after: per-process dir
 destDir := filepath.Join(os.TempDir(), fmt.Sprintf("cli-%d", os.Getpid()))
Defensive patterns

Strategy: try-catch

Validate before calling

info, err := os.Stat(binaryPath)
if err == nil && info.Mode()&0o111 == 0 {
    return fmt.Errorf("binary at %s is not executable", binaryPath)
}

Try / catch

if err := buildBundle(...); err != nil {
    if strings.Contains(err.Error(), "failed to stat binary") {
        return retryBuildOnce() // transient race most likely
    }
    return err
}

Prevention

When it happens

Trigger: os.Stat(binaryPath) fails immediately after the chmod step — file removed by an external process (AV scan, cleanup job) between chmod and stat, or handle/permission anomaly on the destination.

Common situations: Aggressive cleanup daemons purging temp dirs mid-build; race with another build removing the same directory; unusual filesystems that fail stat on just-chmodded files.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at go/cmd/bundler/main.go:1066

	); 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 = "."
	}
	licensePath := licensePathForOutput(outputPath)
	if _, err := os.Stat(licensePath); err == nil {
		return nil
	}

View on GitHub (pinned to cd8cf15dc3)