github/copilot-sdk · error

failed to close tarball file

Error message

failed to close tarball file: %w

What it means

After the tarball body is fully copied, downloadCLIBinary closes the tarball file to flush buffered data to disk. If file.Close() fails (flush error, disk full, I/O error), this error wraps it. It exists because Close can fail even when all writes succeeded, and the checksum would otherwise be computed against a partially flushed file.

Solutions

  1. Free disk space on the target filesystem and re-run buildBundle.
  2. Check filesystem health (dmesg / fsck) if close errors persist.
  3. Redirect output (TMPDIR / output dir) to a local, non-network filesystem.
  4. Retry the build after resolving the underlying I/O condition.

Example fix

// before: default temp dir may be on a small tmpfs
// after: point TMPDIR at a filesystem with headroom
os.Setenv("TMPDIR", "/var/tmp")
tarballPath, _, err := downloadCLIBinary(...)
Defensive patterns

Strategy: try-catch

Validate before calling

if st, err := os.Statfs(filepath.Dir(tarballPath)); err == nil && st.Avail < tarballSizeEstimate {
    return fmt.Errorf("not enough space to flush tarball")
}

Try / catch

if _, _, err := downloadCLIBinary(...); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {
        freeSpaceAndRetry()
    }
}

Prevention

When it happens

Trigger: tarballFile.Close() returns non-nil after io.Copy completed — typically ENOSPC on flush, an I/O error on the underlying filesystem, or (on NFS/network mounts) stale handle errors.

Common situations: Disk filling up between file creation and close; building bundles onto a flaky NFS mount or full Docker volume; container filesystem hitting quota.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

	if resp.StatusCode != http.StatusOK {
		return "", "", fmt.Errorf("failed to download: %s", resp.Status)
	}

	// Save tarball to temp file
	tarballPath := filepath.Join(destDir, assetName)
	tarballFile, err := os.Create(tarballPath)
	if err != nil {
		return "", "", fmt.Errorf("failed to create tarball file: %w", err)
	}

	hasher := sha256.New()
	if _, err := io.Copy(io.MultiWriter(tarballFile, hasher), resp.Body); err != nil {
		tarballFile.Close()
		return "", "", fmt.Errorf("failed to save tarball: %w", err)
	}
	if err := tarballFile.Close(); err != nil {
		return "", "", fmt.Errorf("failed to close tarball file: %w", err)
	}
	actualChecksum := fmt.Sprintf("%x", hasher.Sum(nil))
	if actualChecksum != expectedChecksum {
		return "", "", fmt.Errorf(
			"checksum mismatch for %s: expected %s, got %s",
			assetName,
			expectedChecksum,
			actualChecksum,
		)
	}

	// 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(

View on GitHub (pinned to cd8cf15dc3)