github/copilot-sdk · error

failed to create output file

Error message

failed to create output file: %w

What it means

extractFileFromTarballStream creates the destination file (O_CREATE|O_WRONLY|O_TRUNC) inside destDir before streaming tar contents into it. This error wraps the os.OpenFile failure, so the license (or extracted file) could not be created at outPath.

Solutions

  1. Create destDir first: os.MkdirAll(destDir, 0o755) before extraction
  2. Verify write permissions on the directory or run as a user with access
  3. Ensure outPath is not an existing directory
  4. Check disk space / read-only mount if EACCES does not apply

Example fix

// before
if err := extractCLILicense(tarballPath, outputDir); err != nil { return err }
// after
if err := os.MkdirAll(outputDir, 0o755); err != nil { return fmt.Errorf("create output dir: %w", err) }
if err := extractCLILicense(tarballPath, outputDir); err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

if err := os.MkdirAll(destDir, 0o755); err != nil { return err }
probe := filepath.Join(destDir, ".write-probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil { return fmt.Errorf("dest not writable: %w", err) }
os.Remove(probe)

Type guard

func canCreateIn(dir string) bool { p := filepath.Join(dir, ".probe"); if err := os.WriteFile(p, nil, 0o644); err != nil { return false }; os.Remove(p); return true }

Try / catch

if err := extractCLILicense(tarballPath, outputDir); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && (errors.Is(pe.Err, fs.ErrPermission) || errors.Is(pe.Err, fs.ErrNotExist)) {
        return fmt.Errorf("cannot create %s: %w (check dir exists and permissions)", pe.Path, pe.Err)
    }
    return err
}

Prevention

When it happens

Trigger: Called from extractCLILicense when destDir does not exist, the process lacks write permission on destDir or outPath, outPath exists as a directory, or the filesystem is read-only/full.

Common situations: Bundler run as unprivileged user against a root-owned output directory; missing parent directory; SELinux/container mounts with read-only output; disk quota exceeded.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

	if strings.HasSuffix(outputPath, ".zst") {
		return strings.TrimSuffix(outputPath, ".zst") + ".license"
	}
	return outputPath + ".license"
}

func licenseFileName(binaryName string) string {
	if strings.HasSuffix(binaryName, ".zst") {
		return strings.TrimSuffix(binaryName, ".zst") + ".license"
	}
	return binaryName + ".license"
}

// extractFileFromTarballStream writes the current tar entry to disk.
func extractFileFromTarballStream(r io.Reader, destDir, outputName string, mode os.FileMode) error {
	outPath := filepath.Join(destDir, outputName)
	outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
	if err != nil {
		return fmt.Errorf("failed to create output file: %w", err)
	}
	if _, err := io.Copy(outFile, r); err != nil {
		if cerr := outFile.Close(); cerr != nil {
			return fmt.Errorf("failed to extract license: copy error: %v; close error: %w", err, cerr)
		}
		return fmt.Errorf("failed to extract license: %w", err)
	}
	return outFile.Close()
}

// extractFileFromTarball extracts a single file from a .tgz into destDir with a new name.
func extractFileFromTarball(tarballPath, destDir, targetPath, outputName string) error {
	file, err := os.Open(tarballPath)
	if err != nil {
		return err
	}
	defer file.Close()

View on GitHub (pinned to cd8cf15dc3)