github/copilot-sdk · error

failed to hash existing output

Error message

failed to hash existing output: %w

What it means

When the bundle output already exists (idempotent-skip path), buildBundle hashes the existing binary with sha256FileFromCompressed to report/verify integrity. This error wraps any failure reading or hashing that existing output file — typically the file is missing, unreadable, or corrupted mid-write from a previous failed run.

Solutions

  1. Delete the stale output artifacts and rerun the bundler so it re-downloads fresh.
  2. Check file permissions on the output path.
  3. Verify no concurrent process deletes/moves files in the output directory.
  4. Check disk health / mount stability if I/O errors persist.
  5. Run the bundler with exclusive access to the output directory.

Example fix

// before
binaryHash, err := sha256FileFromCompressed(outputPath)
if err != nil {
	return bundleArtifacts{}, fmt.Errorf("failed to hash existing output: %w", err)
}
// after
binaryHash, err := sha256FileFromCompressed(outputPath)
if err != nil {
	fmt.Printf("Existing output unreadable (%v), rebuilding\n", err)
	// fall through to full download path instead of failing
}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Open(outputPath); err != nil {
	// treat cache as invalid; force full rebuild
}
fi, _ := os.Stat(outputPath)
if fi != nil && fi.Size() == 0 {
	// zero-length artifact from an interrupted run — rebuild
}

Try / catch

artifacts, err := buildBundle(...)
if err != nil && strings.HasPrefix(err.Error(), "failed to hash existing output") {
	os.Remove(outputPath) // clear stale cache
	artifacts, err = buildBundle(...) // retry once
}

Prevention

When it happens

Trigger: filesExist(requiredPaths...) returned true, but sha256FileFromCompressed(outputPath) fails — file deleted between the existence check and the hash, permission denied, or an I/O error reading the partially-written artifact.

Common situations: A previous bundler run was killed mid-download leaving a stale/locked file; output file removed by a concurrent clean job; read permissions changed; output on a flaky/network mount.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

func buildBundle(info platformInfo, cliVersion, outputPath, goos string, includeLicense bool) (bundleArtifacts, error) {
	outputDir := filepath.Dir(outputPath)
	if outputDir == "" {
		outputDir = "."
	}
	runtimeArtifactPath := filepath.Join(outputDir, runtimeLibArtifactName(cliVersion, info.runtimePlatform, goos))
	wrapperArtifactPath := filepath.Join(outputDir, runtimeWrapperArtifactName(cliVersion, info.runtimePlatform, info.binaryName))
	assetsArtifactPath := filepath.Join(outputDir, runtimeAssetsArtifactName(cliVersion, info.runtimePlatform))
	requiredPaths := []string{outputPath, runtimeArtifactPath, wrapperArtifactPath, assetsArtifactPath}
	if includeLicense {
		requiredPaths = append(requiredPaths, licensePathForOutput(outputPath))
	}

	if filesExist(requiredPaths...) {
		// Idempotent output avoids re-downloading in CI or local rebuilds.
		fmt.Printf("Output runtime bundle for %s already exists, skipping download\n", info.runtimePlatform)
		binaryHash, err := sha256FileFromCompressed(outputPath)
		if err != nil {
			return bundleArtifacts{}, fmt.Errorf("failed to hash existing output: %w", err)
		}
		runtimeHash, err := sha256FileFromCompressed(runtimeArtifactPath)
		if err != nil {
			return bundleArtifacts{}, fmt.Errorf("failed to hash existing runtime.node: %w", err)
		}
		wrapperHash, err := sha256FileFromCompressed(wrapperArtifactPath)
		if err != nil {
			return bundleArtifacts{}, fmt.Errorf("failed to hash existing runtime wrapper: %w", err)
		}
		assetsHash, err := sha256File(assetsArtifactPath)
		if err != nil {
			return bundleArtifacts{}, fmt.Errorf("failed to hash existing runtime assets: %w", err)
		}
		return bundleArtifacts{outputPath, binaryHash, runtimeArtifactPath, runtimeHash, wrapperArtifactPath, wrapperHash, assetsArtifactPath, assetsHash}, nil
	}

	// Create temp directory for download
	tempDir, err := os.MkdirTemp("", "copilot-bundler-*")

View on GitHub (pinned to cd8cf15dc3)