github/copilot-sdk · error

binary not found after extraction

Error message

binary not found after extraction: %w

What it means

Immediately after extraction, the bundler stats the expected binary path to confirm the wrapper entrypoint actually landed in destDir. If os.Stat fails, the file is missing (or unreadable) despite extraction reporting success, and this error wraps the stat error. It's a post-extraction sanity check.

Solutions

  1. Check antivirus/EDR logs for quarantine of the extracted binary and add an exclusion.
  2. Ensure no concurrent process cleans or mutates destDir during buildBundle.
  3. Verify binaryName/path construction matches what extractFileFromTarball writes.
  4. Re-run the build; a transient filesystem race usually won't recur.

Example fix

// before: shared mutable destDir across parallel builds
// after: unique per-build destination
destDir = filepath.Join(baseDir, fmt.Sprintf("build-%d", os.Getpid()))
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure destDir is writable and not subject to external cleanup
if err := os.MkdirAll(destDir, 0o755); err != nil { return err }
if f, err := os.CreateTemp(destDir, ".probe"); err != nil { return err } else { f.Close(); os.Remove(f.Name()) }

Try / catch

if err := buildBundle(...); err != nil {
    if strings.Contains(err.Error(), "binary not found after extraction") {
        checkAVQuarantineLog(); retryInIsolatedDir()
    }
}

Prevention

When it happens

Trigger: os.Stat(binaryPath) returns non-nil right after extractFileFromTarball succeeded — the binary was written to an unexpected path, deleted, or destDir was modified between extraction and stat.

Common situations: Antivirus/EDR quarantining freshly extracted executables; concurrent builds sharing destDir and clobbering files; extraction writing under a slightly different name; permissions on destDir changed mid-build.

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/002f3abf15fd98a1. Report an issue: GitHub.

Appendix: source

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

	// The SDK release package intentionally omits the legacy SEA binary. Preserve
	// embeddedcli.Path compatibility by installing the runtime wrapper under the
	// historical copilot[.exe] name; the normal client path uses the adjacent
	// wrapper/runtime.node pair directly.
	binaryPath := filepath.Join(destDir, binaryName)
	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
}

View on GitHub (pinned to cd8cf15dc3)