github/copilot-sdk · error

reading runtime asset

Error message

reading runtime asset %q: %w

What it means

installRuntimeAssets extracts an embedded tar archive of runtime assets into the install directory. This error wraps a failure while reading the bytes of one tar entry from the archive stream, meaning the embedded archive itself is corrupt or its reader failed mid-entry. The entry name is included to identify which asset failed.

Solutions

  1. Verify the build produced a complete, uncorrupted embedded asset archive (rebuild the project so go:embed picks up intact files).
  2. Check disk space and I/O health on the machine performing the extraction.
  3. Retry the install; if reproducible, report the corrupted archive to the library maintainers.
Defensive patterns

Strategy: try-catch

Try / catch

if err := client.InstallAt(dir); err != nil {
    if strings.Contains(err.Error(), "reading runtime asset") {
        // embedded archive corrupt: rebuild/reinstall the binary and retry
    }
}

Prevention

When it happens

Trigger: io.ReadAll(tarReader) returns an error while extracting a tar header named header.Name during installAt or installRuntimeAt; the underlying tar reader/pipe was broken or returned an I/O error.

Common situations: A truncated or corrupted embedded binary asset, an interrupted stream feeding the tar reader, or low-level I/O failure while decompressing the embedded archive.

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

Appendix: source

Thrown at go/internal/embeddedcli/embeddedcli.go:401

	tarReader := tar.NewReader(gzipReader)
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("reading runtime assets: %w", err)
		}
		if header.Typeflag != tar.TypeReg {
			continue
		}
		clean := filepath.Clean(filepath.FromSlash(header.Name))
		if !filepath.IsLocal(clean) {
			return fmt.Errorf("unsafe runtime asset path %q", header.Name)
		}
		content, err := io.ReadAll(tarReader)
		if err != nil {
			return fmt.Errorf("reading runtime asset %q: %w", header.Name, err)
		}
		path := filepath.Join(installDir, clean)
		if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
			return fmt.Errorf("creating runtime asset directory: %w", err)
		}
		hash := sha256.Sum256(content)
		mode := os.FileMode(header.Mode & 0777)
		if err := installVerifiedFile(path, bytes.NewReader(content), hash[:], mode, "runtime asset"); err != nil {
			return err
		}
	}
	runtimeAssetsInstalled = true
	return nil
}

func validateRuntimePairConfig(wrapper io.Reader, wrapperHash []byte, node io.Reader, nodeHash []byte, prefix string) {
	if (wrapper == nil) != (node == nil) {
		panic(prefix + "RuntimeExecutable and " + prefix + "RuntimeNode must be provided together")

View on GitHub (pinned to cd8cf15dc3)