github/copilot-sdk · error

failed to hash existing runtime.node

Error message

failed to hash existing runtime.node: %w

What it means

Same idempotent-skip path as the output hash: buildBundle hashes the existing runtime.node artifact with sha256FileFromCompressed and fails if reading it errors. The bundle cannot report consistent hashes without all artifact hashes, so the whole build aborts.

Solutions

  1. Remove the stale runtime.node artifact and rerun to force a clean download.
  2. Check permissions on runtimeArtifactPath.
  3. Ensure no other process is writing/locking the runtime file.
  4. Verify the output directory belongs to the same platform build (don't mix artifact sets).
  5. Check disk space and mount health if read errors persist.

Example fix

// before
runtimeHash, err := sha256FileFromCompressed(runtimeArtifactPath)
if err != nil {
	return bundleArtifacts{}, fmt.Errorf("failed to hash existing runtime.node: %w", err)
}
// after
runtimeHash, err := sha256FileFromCompressed(runtimeArtifactPath)
if err != nil {
	if os.IsNotExist(err) {
		// stale artifact — fall through to re-download
	} else {
		return bundleArtifacts{}, fmt.Errorf("failed to hash existing runtime.node: %w", err)
	}
}
Defensive patterns

Strategy: try-catch

Validate before calling

for _, p := range []string{outputPath, runtimeArtifactPath, wrapperArtifactPath, assetsArtifactPath} {
	f, err := os.Open(p)
	if err != nil { return fmt.Errorf("artifact %s unreadable: %w", p, err) }
	f.Close()
}

Try / catch

artifacts, err := buildBundle(...)
if err != nil && strings.Contains(err.Error(), "runtime.node") {
	os.Remove(runtimeArtifactPath) // drop stale artifact
	artifacts, err = buildBundle(...) // retry
}

Prevention

When it happens

Trigger: filesExist passed but sha256FileFromCompressed(runtimeArtifactPath) fails — runtime.node deleted after the existence check, permission denied, corrupt/partial file from a prior interrupted run, or decompression failure inside the helper.

Common situations: Interrupted previous build left a truncated runtime.node; antivirus or backup tooling locking the file; wrong outputDir reused from a different platform build; permissions changed after first run.

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

Appendix: source

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

	}
	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-*")
	if err != nil {
		return bundleArtifacts{}, fmt.Errorf("failed to create temp dir: %w", err)
	}
	defer os.RemoveAll(tempDir)

View on GitHub (pinned to cd8cf15dc3)